<?php
// +----------------------------------------------------------------------
// | 登录服务服务层
// +----------------------------------------------------------------------
// | 主要服务于登录数据处理
// +----------------------------------------------------------------------
// | 错误编码头 209xxx
// +----------------------------------------------------------------------
namespace common\service;

use common\exception\LogicException;
use common\model\CategoryModel;
use common\model\CosMediaModel;
use common\model\EntityModel;
use common\model\MediaModel;
use common\model\ModuleModel;
use common\model\NoteEntityRelationModel;
use common\model\NoteModel;
use common\model\OrderTaskListModel;
use common\model\PlaylistItemVersionModel;
use common\model\PlaylistVersionModel;
use common\model\ProjectMemberModel;
use common\model\ProjectModel;
use common\model\ProjectStepCategoryConfirmConfigModel;
use common\model\RelationNoteEntityRelationModel;
use common\model\RepairOrderAffectedTaskModel;
use common\model\RepairTaskWorkOrderRelationModel;
use common\model\ReviewRequestModel;
use common\model\ReviewRequestNodeModel;
use common\model\StatusModel;
use common\model\StepCategoryModel;
use common\model\StepModel;
use common\model\TagModel;
use common\model\TaskMemberModel;
use common\model\TaskModel;
use common\model\TaskRelationTagModel;
use common\model\TaskRepairOrderModel;
use common\model\TaskWorkOrderModel;
use common\model\TaskWorkOrderProblemStepCategoryModel;
use common\model\TaskWorkOrderTaskListModel;
use common\model\TaskWorkOrderUserModel;
use common\model\UserModel;
use common\model\VersionModel;
use support\EntityTaskFilterParser;
use support\ErrorCode;
use support\SingletonTrait;
use think\Exception;
use think\Hook;
use think\module\Module;
use Throwable;
use Webman\Stomp\Client;

class TaskWorkOrderService
{
    private $versionModel;
    private $taskWorkOrderModel;
    private $taskWorkOrderUserModel;

    use EntityTaskFilterParser;

    // 单例工具
    use SingletonTrait;

    protected $workChatListQueryFields = [
        'task_work_order.status',
        'entity.name',
        'entity.initial_episode_code',
        'entity.showings_number',
        'task_work_order.id',
        'task_work_order.chat_global_id',
        'task_work_order.id',
        'task_work_order.number',
        'task_work_order.task_id',
        'entity.project_id',
        'project.name as project_name',
        'step.name as step_name',
    ];

	protected $taskWorkOrderFields = [
		'task_work_order.id',
		'task_work_order.number',
		'task_work_order.name',
		'task_work_order.report_type',
		'task_work_order.report_content',
		'task_work_order.relate_step_category_id',
		'task_work_order.created',
		'task_work_order.processed_people',
		'task_work_order.treatment',
		'task_work_order.incidence',
		'task_work_order.status ',
		'task_work_order.project_id',
		'task_work_order.created_by',
		'task_work_order.receiver',
		'task_work_order.close_at',
		'task_work_order.type',
		'task_work_order.category_id',
		'task_work_order.deadline_time',
		'entity.id',
		'entity.name',
		'entity.code',
		'entity.initial_episode_code',
		'entity.showings_number',
		'entity.json',
		'entity.module_id',
		'task.id',
		'task.step_id',
		'task.step_category_id'
	];

    /**
     * VersionService constructor.
     */
    public function __construct()
    {
        $this->versionModel = model(VersionModel::class);
        $this->taskWorkOrderModel = model(TaskWorkOrderModel::class);
        $this->taskWorkOrderUserModel = model(TaskWorkOrderUserModel::class);
    }

    /**
     * 获得工单号
     * @return string
     * @throws \Exception
     */
    public function getWorkNumber()
    {
        $taskWorkOrderModel = model(TaskWorkOrderModel::class);
        $oldNumber = [];
        while (true) {
            $number = date("YmdHi") . random_int(100, 999);
            if (isset($oldNumber[$number])) {
                continue;
            }
            $taskWorkOrder = $taskWorkOrderModel->where(['number' => $number])->find();
            if (empty($taskWorkOrder)) {
                return $number;
            } else {
                $oldNumber[$number] = $number;
            }

        }
    }

    /**
     * 创建工单
     * @param $data
     * @param $tenantId
     * @param $userId
     * @param $unionId
     * @param bool $createNote 是否创建反馈记录
     * @return array
     * @throws Exception
     * @throws Throwable
     */
    public function createTaskWorkOrder($data, $tenantId, $userId, $unionId, $createNote = true)
    {
        $task = model(TaskModel::class)
            ->field('name,project_id,entity_id,step_category_id,step_id')
            ->find($data['task_id']);
        if (empty($task)) {
            throw new LogicException("task not found", ErrorCode::TASK_NOT_FOUND);
        }

        $reviewRequestNodeId = $data['review_request_node_id'] ?? 0;
        $versionId = $data['version_id'] ?? 0;
        $data['receiver'] = $data['receiver'] ?? [];
        $problemStepCategoryIds = $data['problem_step_category_ids'] ?? [];
        $data['report_category'] = $data['report_category'] ?? "instantly_deal";
        $data['is_confirm'] = $data['is_confirm'] ?? TaskWorkOrderProblemStepCategoryModel::IS_CONFIRM_DEFAULT;
        $number = $this->getWorkNumber();
        $taskData = [
            'type' => $data['type'],
            'number' => $number,
            'version_id' => $versionId,
            'review_request_node_id' => $reviewRequestNodeId,
            'created_by' => $userId,
            'task_id' => $data['task_id'],
            'text' => $data['text'] ?? "",
            'receiver_unread' => 'yes',
            'name' => $data["name"] ?? "",
            'project_id' => $task['project_id'],
            'report_type' => $data['reason_type'] ?? 'unknown',
            'category_id' => $data['category_id'] ?? 0,
            'report_content' => $data['text'] ?? "",
            "entity_id" => $task['entity_id'],
            "step_category_id" => $task['step_category_id'],
            "step_id" => $task['step_id']
        ];
        //填补默认名称
        if (empty($taskData['name'])) {
            $taskData['name'] = $this->getDefaultWorkOrderName($task);
        }

        //检测是否能创建工单
        $reviewRequest = $this->checkCreateTaskWorkOrderData($data);

        //report_category : instantly_deal立即处理,only_report仅上报
        //立即处理不创建群聊
        if ($data['report_category'] == 'instantly_deal') {
            $memberUnionIds = $this->getTaskWorkOrderDefaultOptionMember($problemStepCategoryIds, $task['project_id']);
            $data['receiver'] = array_merge($data['receiver'], $memberUnionIds);
        }


        //是否需要创建群聊
        $taskWorkOrderUser = [$userId];
        $taskWorkOrderUnionId = [];
        if (!empty($data['receiver'])) {
            $taskWorkOrderUnionId = array_unique(array_merge([$unionId], $data['receiver']));
            $taskWorkOrderUser = model(UserModel::class)
                ->where(['union_id' => ["IN", $taskWorkOrderUnionId]])
                ->field("id")
                ->column('id');
        }

        // 创建工单,media
        $mediaService = MediaService::getInstance();
        $mediaModel = model(MediaModel::class);
        $commonService = CommonService::instance('task_work_order');
        $taskWorkOrderModel = model(TaskWorkOrderModel::class);
        // 开启事务
        $taskWorkOrderModel->startTrans();
        try {
            if (!empty($data['note_media'])) {
                $mediaIds = [];
                foreach ($data['note_media'] as $mediaItem) {
                    $mediaService->generateMediaData($mediaItem);
                    $mediaData = $mediaModel->addItem($mediaItem);
                    if (!$mediaData) {
                        throw new LogicException($mediaModel->getError(), ErrorCode::MEDIA_ADD_FAILURE);
                    } else {
                        $mediaIds[] = $mediaData['id'];
                    }
                }
                if (!empty($mediaIds)) {
                    $taskData['task_work_order_media'] = join(',', $mediaIds);
                }
            }
            $createTaskWorkOrder = $commonService->create($taskData);
            $createTaskWorkOrderId = $createTaskWorkOrder['id'];
            if (!$createTaskWorkOrder) {
                throw new LogicException(
                    model(TaskWorkOrderModel::class)->getError(),
                    model(TaskWorkOrderModel::class)->getErrorCode()
                );
            }

            //组装问题环节的数据
            $problemStepCategoryData = [];
            foreach ($problemStepCategoryIds as $problemStepCategoryId) {
                $problemStepCategoryData[] = [
                    'task_work_order_id' => $createTaskWorkOrderId,
                    'step_category_id' => $problemStepCategoryId,
                    'project_id' => $task['project_id'],
                    'is_confirm' => $data['is_confirm'],
                    'uuid' => create_uuid(),
                    'created_by' => $userId,
                    'created' => time()
                ];
            }

            if (!empty($problemStepCategoryData)) {
                model(TaskWorkOrderProblemStepCategoryModel::class)->addAll($problemStepCategoryData);
            }

            //添加工单用户
            $addWorkOrderUser = [];

            foreach ($taskWorkOrderUser as $user) {
                if (empty($user)) {
                    continue;
                }
                $addWorkOrderUser[] = [
                    'user_id' => $user,
                    'work_order_id' => $createTaskWorkOrderId,
                    'created' => time()
                ];
            }
            model(TaskWorkOrderUserModel::class)->addAll($addWorkOrderUser);

            //创建Note
            $noteRes = null;
            if ($createNote) {
                $noteRes = $this->addTaskWorkOrderNote(
                    $data,
                    $taskData,
                    $tenantId,
                    $createTaskWorkOrder,
                    $reviewRequest
                );
            }

            //创建工单会话 (返修工单不创建)
            if (!empty($data['receiver'])) {
                $this->addTaskWorkOrderChat($taskWorkOrderUnionId, $createTaskWorkOrder, $taskData);
            }
            $taskWorkOrderModel->commit();
            return [
                'task_work_order' => $createTaskWorkOrder,
                'note_res' => $noteRes
            ];
        } catch (Throwable $e) {
            $taskWorkOrderModel->rollback();
            throw $e;
        }
    }

    /**
     * 查询资产任务工单查询
     * @param $param
     * @param $currentUserId
     * @param $currentTenantId
     * @return array|false|mixed|string
     * @throws \Exception
     */
    public function selectAssetTaskWorkOrderSelect($param, $currentUserId, $currentTenantId)
    {
        $page = $param['page'] ?? [1, C('default_page_total')];

//        $stepCategoryId = $param['filter']['step_category_id'];
//        $module = $this->getModuleByStepCategoryId($stepCategoryId);
        $taskWorkOrderType = $param['filter']['task_work_order_type'];
        $filter = $this->parseMultipleEntityTaskFilter($param['filter']);
        $statusList = array_column(model(StatusModel::class)->field('id,code')->select(), 'id', 'code');

        $filter['task.step_type'] = 'step';
//        $filter['entity.module_id'] = $module['id'];
        $filter['task_work_order.receiver'] = $currentUserId;
        $filter['task_work_order.type'] = $taskWorkOrderType;
        $filter["JSON_UNQUOTE(JSON_EXTRACT(entity.json, CONCAT('$.', module.code, '_status')))"] = ['NEQ', $statusList['closed']];

        $taskWorkOrderFields = [
            "task_work_order.id", "task_work_order.number",
            "task_work_order.status", "task_work_order.created_by",
            "task_work_order.receiver", "task_work_order.task_id",
            "task_work_order.version_id", "task_work_order.review_request_node_id",
            "task.executor_tenant_id", "task.tenant_id", "task_work_order.created_by",
            "entity.name as entity_name", "entity.initial_episode_code",
            "entity.showings_number", "entity.module_id", "entity.entity_id",
            "task.executor", "task.entity_id as task_entity_id",
            "entity.entity_module_id", "task.name as step_name",
            "task_work_order.type as task_work_order_type",
            "JSON_UNQUOTE(JSON_EXTRACT(entity.json,CONCAT('$.',module.`code`,'_category') )) AS category",
            "JSON_UNQUOTE(JSON_EXTRACT(entity.json,CONCAT('$.',module.`code`,'_grade') )) AS grade",
            "entity.initial_episode_code","entity.showings_number"
        ];


        $taskWorkOrderList = model(TaskWorkOrderModel::class)
            ->join('task on task.id = task_work_order.task_id')
            ->join('entity on entity.id = task.entity_id')
            ->join('module on module.id = entity.module_id')
            ->where($filter)
            ->field($taskWorkOrderFields)
            ->page($page[0], $page[1])
            ->select();

        if (!empty($taskWorkOrderList)) {
            $taskIds = array_unique(array_column($taskWorkOrderList, 'task_id'));
            $versionIds = array_column($taskWorkOrderList, 'version_id');

            //查询版本
            $versions = $this->versionModel->where(['id' => ["IN", $versionIds]])->field('id,number')->select();
            $versions = array_column($versions, 'number', 'id');

            $queryFields = [
                'task.id', 'task.name',
                'task.plan_end_time', 'task.executor',
                'task.executor_tenant_id', 'task.tenant_id',
                'entity.id as entity_id'
            ];

            // 查询任务和实体数据
            $data = model(EntityModel::class)
                ->join('task on task.entity_id = entity.id')
                ->where(['task.id' => ['IN', $taskIds]])
                ->field($queryFields)
                ->select();
            $outsideSupplierTenantId = [];
            $executorUserIdList = [];
            $parentEntityIdList = [];
            foreach ($data as $task) {
                if ($task['executor_tenant_id'] > 0 && $task['executor_tenant_id'] != $currentTenantId) {
                    $outsideSupplierTenantId[$task['executor_tenant_id']] = $task['executor_tenant_id'];
                } else if ($task['executor'] > 0) {
                    $executorUserIdList[$task['executor']] = $task['executor'];
                }
                if ($task['entity_id'] > 0) {
                    $parentEntityIdList[$task['entity_id']] = $task['entity_id'];
                }
            }


            // 供应商信息
            $taskService = TaskService::getInstance();
            $supplierRes = $taskService->queryTaskSupplierInfo(
                $currentTenantId, [],
                array_values($outsideSupplierTenantId), [],
                array_values($executorUserIdList)
            );

            $sequenceList = $this->getEntityListMap($parentEntityIdList);

            //执行人名称 ,环节制片名称
            $createdByIds = array_column($taskWorkOrderList, 'created_by');
            $userNames = model(UserModel::class)
                ->where(['id' => ['IN', $createdByIds]])
                ->field('id,name')
                ->select();
            $userNames = array_column($userNames, 'name', 'id');

            //工单下的问题描述 (拿取每个工单的第一条)
            $taskWorkOrderIds = array_column($taskWorkOrderList, 'id');
            $notes = $this->getProblemDescription($taskWorkOrderIds);

            $dataFormatCallback = function ($item) use ($versions, $notes, $userNames, $supplierRes) {
                $item['created_by_name'] = $userNames[$item['created_by']] ?? "";
                //填充计划时间,分类,等级,实体名
                $item['executor_name'] = "";
                if ($item['executor_tenant_id'] > 0 && $item['executor_tenant_id'] != $item['tenant_id']) {
                    $item['executor_name'] = $supplierRes['outside'][$item['executor_tenant_id']]['name'] ?? "";
                } elseif ($item['executor'] > 0) {
                    $item['executor_name'] = $supplierRes['executor'][$item['executor']]['name'] ?? "";
                }
                //填充上报问题
                $item['text'] = $notes[$item['id']] ?? "";
                //填充版本
                $item['version_number'] = $versions[$item['version_id']] ?? null;
                return $item;
            };
            // ["-...-"]
            $dataFormatCallbackSub = $dataFormatCallback;
            $dataFormatCallback = function ($item) use (&$dataFormatCallbackSub, &$sequenceList) {
                $item = $dataFormatCallbackSub($item);
                if (isset(Module::$moduleDictData['module_index_by_id'][$item['entity_module_id']]['code'])) {
                    $item[Module::$moduleDictData['module_index_by_id'][$item['entity_module_id']]['code']] = $sequenceList[$item['task_entity_id']]['name'] ?? "";
                }
                return $item;
            };

            //填充其他表数据
            $taskWorkOrderList = array_map($dataFormatCallback, $taskWorkOrderList);
        }
        return $taskWorkOrderList;
    }

    /**
     * 获取最后一条工单信息
     * @param $taskIds
     * @param string $type
     * @return array
     */
    public function getMaxTaskWorkMap($taskIds, $type = "task_making")
    {
        //工单状态
        if (empty($taskIds)) {
            return [];
        }

        $taskWorkOrderIds = model(TaskWorkOrderModel::class)->where([
            'task_id' => ['IN', $taskIds],
            'type' => $type
        ])->field('max(id) as id')->group('task_id')->select();
        $taskWorkOrderMap = [];
        if (!empty($taskWorkOrderIds)) {
            $taskWorkOrderIds = array_column($taskWorkOrderIds, 'id');
            $taskWorkOrderMap = model(TaskWorkOrderModel::class)
                ->where([
                'id' => ['IN', $taskWorkOrderIds],
            ])->field('task_id,status,id')->select();
            $taskWorkOrderMap = array_column($taskWorkOrderMap, null, 'task_id');
        }
        return $taskWorkOrderMap;
    }


    /**
     * 获取多个任务的问题描述
     * @param $taskWorkOrderIds
     * @return array
     */
    public function getProblemDescription($taskWorkOrderIds)
    {
        $notes = [];
        if (!empty($taskWorkOrderIds)) {
            $minNoteIds = model(TaskWorkOrderModel::class)
                ->join("note on task_work_order.id = note.link_id")
                ->where([
                    'link_id' => ['IN', $taskWorkOrderIds],
                    'module_id' => Module::$moduleDictData['module_index_by_code']['task_work_order']['id'],
                ])->field('min(note.id) as id')
                ->group('task_work_order.id')
                ->select();
            $minNoteIds = array_column($minNoteIds, 'id');
            if (!empty($minNoteIds)) {
                $notes = model(NoteModel::class)
                    ->where(['id' => ['IN', $minNoteIds]])
                    ->field('link_id,text')
                    ->select();
                $notes = array_column($notes, 'text', 'link_id');
            }
            return $notes;
        }
        return [];
    }


    /**
     * 通过指定Task ID 获取所有甲乙双方的任务ids
     * @param $taskId
     * @return array
     */
    public function getALLOrderTaskIdsByTaskId($taskId = 0)
    {
        // 甲方任务ID
        $partyATaskId = model(OrderTaskListModel::class)
            ->where([
                "real_task_id" => $taskId
            ])
            ->field("task_id")
            ->find();
        if (empty($partyATaskId['task_id'])) {
            $partyATaskId = $taskId;
        } else {
            $partyATaskId = $partyATaskId['task_id'];
        }
        // 外包任务IDs
        $realTaskIds = model(OrderTaskListModel::class)
            ->where([
                "task_id" => $partyATaskId
            ])
            ->field("real_task_id")
            ->column('real_task_id');

        $realTaskIds[] = (int)$partyATaskId;
        return $realTaskIds;
    }

    /**
     * 获取当前单个任务所有包含甲乙双方的工单列表
     * @param $filter
     * @param $page
     * @return array
     * @throws \Exception
     */
    public function getTaskALLWorkOrderRecords($filter, $page)
    {
        // 获取任务甲方，乙方所有任务ID
        if (array_key_exists("task_id", $filter)) {
            $filter['task_id'] = ['in', $this->getALLOrderTaskIdsByTaskId($filter['task_id'])];
        }
        return $this->taskWorkOrderRecordTree($filter, $page);
    }

    /**
     * 当前用户的工单记录树
     * @param $filter
     * @param $page
     * @return array
     * @throws \Exception
     */
    public function taskWorkOrderRecordTree($filter, $page)
    {
        $taskWorkOrderField = [
            'task_work_order.id', 'task_work_order.number',
            'task_work_order.status', 'task_work_order.version_id',
            'task_work_order.task_id', 'task_work_order.created_by',
            'task_work_order.receiver', 'task_work_order.review_request_node_id',
            'task_work_order.type',
            "JSON_UNQUOTE(JSON_EXTRACT(task_work_order.json,'$.task_work_order_tag' )) AS task_work_order_tag",
            'task_work_order.chat_global_id',
            "JSON_UNQUOTE(JSON_EXTRACT(json,'$.task_work_order_media' )) AS task_work_order_media",
            'task_work_order.report_type', 'task_work_order.report_content',
            'task_work_order.created', 'task_work_order.category_id'
        ];

        $taskWorkOrderGroup = model(TaskWorkOrderModel::class)
            ->join("task_work_order_user on task_work_order_user.work_order_id = task_work_order.id")
            ->where($filter)
            ->page($page[0], $page[1])
            ->field("task_work_order.id")
            ->order('id desc')
            ->group("task_work_order.id")
            ->select();

        if (empty($taskWorkOrderGroup)) {
            return [];
        }

        $taskWorkOrderIds = array_column($taskWorkOrderGroup, 'id');
        $taskWorkOrder = model(TaskWorkOrderModel::class)->where(['id' => ["IN", $taskWorkOrderIds]])->field($taskWorkOrderField)->select();

        if (empty($taskWorkOrder)) {
            return [];
        }

        $userData = model(UserModel::class)->field("id,phone,email,name,union_id,avatar")
            ->where(['id' => ['IN', array_column($taskWorkOrder, 'created_by')]])
            ->select();
        $userMap = array_column($userData, null, 'id');
        $categoryIdList = array_column($taskWorkOrder, 'category_id', 'category_id');
        unset($categoryIdList[0]);

        $categoryList = [];
        if (!empty($categoryIdList)) {
            $categoryList = CategoryService::getInstance()->getCategoryListWithParent($categoryIdList);
            $categoryList = array_column($categoryList, null, 'id');
        }

        return array_map(function ($workOrderItem) use ($userMap, $categoryList) {
            $workOrderInformation = [
                'type' => $workOrderItem['type'] ?? '',
                'report_type' => $workOrderItem['report_type'] ?? '',
                'report_content' => $workOrderItem['report_content'] ?? '',
                'problem_description' => [
                    'tenant_position_name' => "",
                    'user' => $userMap[$workOrderItem['created_by']] ?? [],
                    'text' => $workOrderItem["report_content"],
                    'reason_type' => $workOrderItem["report_type"],
                    'note_media' => null,
                    "created_by" => $workOrderItem['created_by'],
                    "created" => $workOrderItem['created'],
                ],
            ];

            $workOrderItem['work_order_information'] = $workOrderInformation;
            $workOrderItem['task_work_order_category'] = $categoryList[$workOrderItem['category_id']] ?? null;
            $workOrderItem['task_work_order_category_parent'] = $workOrderItem['task_work_order_category']['parent'] ?? null;
            return $workOrderItem;
        }, $taskWorkOrder);
    }

    /**
     * 获取工单详细信息
     * @param $taskWorkOrderId
     * @param $tenantId
     * @param $userId
     * @return array|false|mixed|string|null
     * @throws \Exception
     */
    public function taskWorkOrderInformation($taskWorkOrderId, $tenantId, $userId)
    {
        $queryFields = [
            "id", "number", "status", "version_id",
            "task_id", "created_by",
            "receiver", "review_request_node_id", "type",
            "JSON_UNQUOTE(JSON_EXTRACT(json,'$.task_work_order_tag' )) AS task_work_order_tag",
            "chat_global_id",
            "JSON_UNQUOTE(JSON_EXTRACT(json,'$.task_work_order_media' )) AS task_work_order_media",
            "report_type", "report_content", "created", "relate_step_category_id",
            "processed_people", "treatment", "incidence",
            'project_id', 'solution', 'category_id', 'deadline_time',
        ];
        $taskWorkOrder = model(TaskWorkOrderModel::class)
            ->field($queryFields)
            ->find($taskWorkOrderId);

        if (empty($taskWorkOrder)) {
            return [];
        }

        if (!empty($taskWorkOrder['task_work_order_tag'])) {
            $taskWorkOrder['tag'] = model(TagModel::class)
                ->field('id,name,type,color')
                ->find($taskWorkOrder['task_work_order_tag']);
        }
        $taskWorkOrder['remove_deny'] = UserService::getInstance()->userIdTransform([$taskWorkOrder['created_by'], $taskWorkOrder['receiver']], 'saas');

        $reviewPlanEndTime = 0;
        if ($taskWorkOrder['type'] === 'review_feedback') {
            $reviewRequestNode = model(ReviewRequestNodeModel::class)
                ->field('id,feedback_status,review_request_id,role_code')
                ->find($taskWorkOrder['review_request_node_id']);
            $taskWorkOrder['feedback_status'] = $reviewRequestNode['feedback_status'];
            $taskWorkOrder['review_request_id'] = $reviewRequestNode['review_request_id'];
            $playlistItemVersion = model(PlaylistItemVersionModel::class)
                ->where(['review_request_id' => $reviewRequestNode['review_request_id']])
                ->field('playlist_version_id')
                ->find();
            $playlistVersion = model(PlaylistVersionModel::class)
                ->field('plan_end_time')
                ->find($playlistItemVersion['playlist_version_id']);
            $reviewPlanEndTime = $playlistVersion['plan_end_time'];
        }

        $taskWorkOrder['version_number'] = null;
        if (!empty($taskWorkOrder['version_id'])) {
            $version = model(VersionModel::class)->field('number')->find($taskWorkOrder['version_id']);
            if (!empty($version)) {
                $taskWorkOrder['version_number'] = $version['number'];
            }
        }

        $note = [];
        $user = model(UserModel::class)
            ->field("id,phone,email,name,union_id,avatar")
            ->find($taskWorkOrder['created_by']);
        $userRole = $this->getUserRole([$user['id']], $tenantId);
        $note['tenant_position_name'] = $userRole[$taskWorkOrder['created_by']] ?? "";
        $note['user'] = $user;
        $note['text'] = $taskWorkOrder["report_content"];
        $note['reason_type'] = $taskWorkOrder["report_type"];
        $note['note_media'] = null;
        $note["created_by"] = $taskWorkOrder['created_by'];
        $note["created"] = $taskWorkOrder['created'];
        $noteMedia = $taskWorkOrder['task_work_order_media'];
        unset($taskWorkOrder['note_media']);
        if (!empty($noteMedia)) {
            $mediaList = model(MediaModel::class)->where([
                'id' => ["IN", $noteMedia]
            ])->field('id,thumb,param')->select();
            $mediaList = array_map(function ($mediaItem) {
                $mediaItem['param'] = json_decode($mediaItem['param'], true);
                return $mediaItem;
            }, $mediaList);
            $note['note_media'] = $mediaList;
        }

        $taskField = [
            'task.plan_end_time', 'task.project_id',
            'task.name as task_name',
            'task.step_category_id as task_step_category_id', 'task.step_id task_step_id',
            'entity.id as entity_id',
            'entity.initial_episode_code',
            'entity.showings_number',
            'entity.name as entity_name',
            'entity.director_star',
            'entity.key_shot',
            'module.code as entity_module_code',
            "JSON_UNQUOTE(JSON_EXTRACT(entity.json,CONCAT('$.',module.`code`,'_category') )) AS category",
            "JSON_UNQUOTE(JSON_EXTRACT(entity.json,CONCAT('$.',module.`code`,'_grade') )) AS grade",
            "JSON_UNQUOTE(JSON_EXTRACT(task.json,'$.is_dismantle_task' )) AS is_dismantle_task",
        ];

        $task = model(TaskModel::class)
            ->join('entity on entity.id= task.entity_id')
            ->join('module on module.id = entity.module_id')
            ->where(['task.id' => $taskWorkOrder['task_id']])
            ->field($taskField)
            ->find();
        if (empty($task)) {
            return [];
        }

        $taskWorkOrder['task_step_category'] = StepCategoryService::getInstance()->getOne(['id' => $task['task_step_category_id']], 'id,name,code');
        $taskWorkOrder['task_step'] = StepService::getInstance()->getStep($task['task_step_id'], 'id,name,code,color');
        $taskWorkOrder['task_work_order_category'] = $taskWorkOrder['task_work_order_category_parent'] = null;
        if ($taskWorkOrder['category_id'] > 0) {
            $category = CategoryService::getInstance()->getCategoryWithParent($taskWorkOrder['category_id']);
            $taskWorkOrder['task_work_order_category'] = $category;
            $taskWorkOrder['task_work_order_category_parent'] = $category['parent'];
        }
        $taskStatus = StatusService::getInstance()->getList([], "*");

        $getTaskMemberFilterData['step_type'] = 'work_order_to_do';
        $getTaskMemberFilterData['status_code'] = 'not_started';
        $getTaskMemberFilterData['task.tenant_id'] = $tenantId;
        $getTaskMemberFilterData['task.entity_module_id'] = module_by_code('todo')['id'];

        $findNotStartedWhere = TaskMemberService::getInstance()->getTaskMemberFilter($getTaskMemberFilterData, $taskStatus, $userId);
        $findNotStartedWhere[] = [
            "JSON_UNQUOTE(JSON_EXTRACT(task.json, '$.task_work_order_id'))" => $taskWorkOrderId
        ];

        $findNotStartedData = model(TaskMemberModel::class)
            ->field('task.id')
            ->where($findNotStartedWhere)
            ->join("task ON task_member.task_id = task.id")
            ->join("project ON task.project_id = project.id", 'LEFT')
            ->group('task_id')
            ->find();

        // 工单问题详情小红点
        $isWaitTask = false;
        if ($findNotStartedData) {
            $isWaitTask = true;
        }

        //获取工单下的返修工单状态
        //  0 正在返修 > 1 完成返修 >null 无返修
        $repairStatus = null;
        $repairTaskWorkOrderStatus = model(RepairTaskWorkOrderRelationModel::class)
            ->join("task_repair_order on task_repair_order.id = repair_task_work_order_relation.task_repair_order_id")
            ->where(['repair_task_work_order_relation.task_work_order_id' => $taskWorkOrderId])
            ->field("task_repair_order.status")
            ->select();

        if (!empty($repairTaskWorkOrderStatus)) {
            $repairTaskWorkOrderStatus = array_column($repairTaskWorkOrderStatus, 'status');
            if (in_array("default", $repairTaskWorkOrderStatus)) {
                $repairStatus = "default";
            } else {
                $repairStatus = "done";
            }
        }

        // 获取工单归属类型：甲方、集团内乙方、供应商乙方
        $project = model(ProjectModel::class)->where(['id' => $task['project_id']])->find();
        $taskWorkOrder['belong_type'] = 'default';
        $taskWorkOrder['belong_project_id'] = $project['belong_project_id'];
        $taskWorkOrder['project_id'] = $project['id'];
        $taskWorkOrder['current_tenant_type'] = 'default';
        $taskWorkOrder['project_tenant_id'] = $project['tenant_id'];
        $taskWorkOrder['belong_project_tenant_id'] = 0;
        switch ($project['type']) {
            case "insource":
                // 直接归属为甲方
                $taskWorkOrder['belong_type'] = "inside";
                $requestData['param'] = [
                    "filter" => [
                        'project_tenant_id' => $project['tenant_id']
                    ]
                ];
                $tenantGroupMember = teamones_request('teamones-im', 'tenant_group_member/get_tenant_group_member_by_project', $requestData)['data'];
                if ($tenantId == $project['tenant_id']) {
                    $taskWorkOrder['current_tenant_type'] = 'inside';
                } else if (in_array($tenantId, $tenantGroupMember['tenant_group_member_ids'])) {
                    $taskWorkOrder['current_tenant_type'] = 'tenant_group_outside';
                } else {
                    $taskWorkOrder['current_tenant_type'] = 'outside';
                }
                break;
            case "outsource":
                // 判断是哪种情况下的乙方
                $belongProject = model(ProjectModel::class)->where(['id' => $project['belong_project_id']])->find();
                $taskWorkOrder['belong_project_tenant_id'] = $belongProject['tenant_id'];
                $requestData['param'] = [
                    "filter" => [
                        'project_tenant_id' => $belongProject['tenant_id']
                    ]
                ];
                $tenantGroupMember = teamones_request('teamones-im', 'tenant_group_member/get_tenant_group_member_by_project', $requestData)['data'];
                // 在集团内就是集团乙方，不在就是供应商乙方
                if (in_array($project['tenant_id'], $tenantGroupMember['tenant_group_member_ids'])) {
                    $taskWorkOrder['belong_type'] = 'tenant_group_outside';
                } else {
                    $taskWorkOrder['belong_type'] = 'outside';
                }
                if ($tenantId == $belongProject['tenant_id']) {
                    $taskWorkOrder['current_tenant_type'] = 'inside';
                } else if (in_array($tenantId, $tenantGroupMember['tenant_group_member_ids'])) {
                    $taskWorkOrder['current_tenant_type'] = 'tenant_group_outside';
                } else {
                    $taskWorkOrder['current_tenant_type'] = 'outside';
                }
                break;
        }

        $taskWorkOrder = array_merge($taskWorkOrder, $task);
        $taskWorkOrder['problem_description'] = $note;
        $taskWorkOrder['repair_status'] = $repairStatus;
        $taskWorkOrder['review_plan_end_time'] = $reviewPlanEndTime;
        $taskWorkOrder['is_wait_task'] = $isWaitTask;

        if (in_array($task['entity_module_code'], ['asset', 'design', 'level'])) {
            $taskWorkOrder['asset_or_shot'] = 'asset';
        } else {
            $taskWorkOrder['asset_or_shot'] = 'shot';
        }
        $taskWorkOrder['latest_relate_repair_note'] = $this->getLatestRepairNote($taskWorkOrderId);
        return $taskWorkOrder;
    }

    /**
     * 查询最新一条返修反馈记录
     * @param $taskWorkOrderId
     * @return array|false|mixed|string|null
     */
    public function getLatestRepairNote($taskWorkOrderId)
    {
        $latestRelateRepairNoteFilter = [
            'demand_type' => NoteModel::DEMAND_TYPE_REPAIR_FEEDBACK,
            'module_id' => module_by_code('task_work_order')['id'],
            'link_id' => $taskWorkOrderId,
        ];
        return model(NoteModel::class)->where($latestRelateRepairNoteFilter)->order('id desc')->find();
    }

    /**
     * 工单记录详情
     * @param $param
     * @param $tenantId
     * @return array|false|mixed|string
     * @throws \Exception
     */
    public function taskWorkOrderRecordDetails($param, $tenantId)
    {
        $filter = $param['filter'];
        $page = [1, 500];


        //需要排除掉第一条的问题描述
        $problemDescription = model(NoteModel::class)->where([
            'link_id' => $filter['task_work_order_id'],
            'module_id' => Module::$moduleDictData['module_index_by_code']['task_work_order']['id']
        ])->field('min(id) as id')->find();

        if (empty($problemDescription)) {
            throw_strack_exception('note does not exist', ErrorCode::DATA_INVALID);
        }
        $problemDescriptionId = $problemDescription['id'];
        $note = model(NoteModel::class)
            ->join("user on user.id = note.created_by", "LEFT")
            ->where([
                'link_id' => $filter['task_work_order_id'],
                'module_id' => Module::$moduleDictData['module_index_by_code']['task_work_order']['id'],
                'note.id' => ['NEQ', $problemDescriptionId]
            ])
            ->page($page[0], $page[1])
            ->field("note.id,text,user.id as user_id,user.name as user_name,user.avatar,JSON_UNQUOTE(JSON_EXTRACT(note.json,'$.note_media' )) AS note_media,note.created")
            ->order('note.id asc')
            ->select();

        if (!empty($note)) {
            //用户信息
            $userIds = array_column($note, 'user_id');

            $userRole = $this->getUserRole($userIds, $tenantId);

            //图片信息
            $noteMedia = array_column($note, 'note_media', 'id');
            $medias = array_filter($noteMedia, function ($noteMediaItem) {
                return !empty($noteMediaItem);
            });

            $mediaArray = join(',', array_values($medias));
            $mediaList = [];
            if (!empty($mediaArray)) {
                $mediaList = model(MediaModel::class)->where([
                    'id' => ["IN", $mediaArray]
                ])->field('id,thumb')->select();
                $mediaList = array_column($mediaList, null, 'id');
            }

            //填充图片
            foreach ($note as &$noteItem) {
                unset($noteItem['note_media']);
                $noteItem['media'] = [];
                if (!empty($medias[$noteItem['id']])) {
                    $currentMediaList = explode(',', $medias[$noteItem['id']]);
                    foreach ($currentMediaList as $currentMediaItem) {
                        if (!empty($mediaList[$currentMediaItem])) {
                            $noteItem['media'][] = $mediaList[$currentMediaItem];
                        }
                    }
                }
                $noteItem['tenant_position_name'] = "";
                if (array_key_exists($noteItem['user_id'], $userRole)) {
                    $noteItem['tenant_position_name'] = $userRole[$noteItem['user_id']];
                }
            }
        }


        return $note;
    }

    /**
     * 获取用户角色
     * @param $syncIds
     * @param $tenantId
     * @return array
     * @throws \Exception
     */
    public function getUserRole($syncIds, $tenantId)
    {
        $userList = model(UserModel::class)->where(['id' => ['IN', $syncIds]])->field('id,union_id')->select();
        if (!empty($userList)) {
            $userIdMap = array_column($userList, 'id', 'union_id');
            $unionIds = array_column($userList, 'union_id');

            $requestData = ["param" => [
                "filter" => [
                    "id" => ['-in', implode(',', $unionIds)],
                ],
            ]];
            $data = teamones_request('teamones-im', 'user/get_other_users_info', $requestData)['data'];
            $data = $data ?? [];

            if (!empty($data)) {
                $res = [];
                foreach ($data as $item) {
                    if (!empty($item['tenant_position'])) {
                        $res[$userIdMap[$item['user']['id']]] = $item['tenant_position']['name'];
                    }
                }
                return $res;
            }
        }


        return [];

    }

    /**
     * 回复工单
     * @param $data
     * @param $tenantId
     * @param $userId
     * @return array|false|mixed|string|null
     * @throws Throwable
     */
    public function replyTaskWorkOrder($data, $tenantId, $userId)
    {
        $taskWorkOrderId = $data['task_work_order_id'];

        $noteData = [
            "note" => [
                'type' => 'text',
                'tenant_id' => $tenantId,
                'link_id' => $taskWorkOrderId,
                'module_id' => Module::$moduleDictData['module_index_by_code']['task_work_order']['id'],
                'text' => $data['text'],
            ],
            'note_media' => $data['note_media'] ?? []
        ];

        //小红点更新
        $taskWorkOrder = model(TaskWorkOrderModel::class)->field('id,created_by,receiver')->find($data['task_work_order_id']);

        $taskWorkOrderList = model(TaskWorkOrderUserModel::class)->where(["work_order_id" => $taskWorkOrder['id']])->field("id,user_id")->select();
        $taskWorkOrderUserIds = [];
        $taskWorkOrderIds = [];
        foreach ($taskWorkOrderList as $taskWorkOrderListItem) {
            $taskWorkOrderUserIds[] = $taskWorkOrderListItem['user_id'];
            $taskWorkOrderIds[$taskWorkOrderListItem['user_id']] = $taskWorkOrderListItem['id'];
        }
        if (!in_array($userId, $taskWorkOrderUserIds)) {
            throw new LogicException('task member user not exist', ErrorCode::TASK_MEMBER_USER_NOT_EXIST);
        }

        $noteRes = NoteService::getInstance()->createNote($noteData);
        if (!empty($noteRes)) {

            //其他工单人员的小红点只会出现在处理按钮中 回复消息的如果是自己 排除自己
            unset($taskWorkOrderIds[$userId]);
            if (!empty($taskWorkOrderIds)) {
                model(TaskWorkOrderUserModel::class)->where(["id" => ["IN", join(",", $taskWorkOrderIds)]])->save(["message_unread" => "yes"]);
            }

            $note = model(NoteModel::class)->field("id,text,created,created_by,JSON_UNQUOTE(JSON_EXTRACT(note.json,'$.note_media' )) AS note_media")->find($noteRes['id']);
            if (!empty($note['note_media'])) {
                $noteMedia = explode(',', $note['note_media']);
                if (!empty($noteMedia)) {
                    $mediaList = model(MediaModel::class)->where(['id' => ["IN", $noteMedia]])->field('id,thumb')->select();
                    $note['note_media'] = $mediaList;
                }
            }
            $user = model(UserModel::class)->field('id,avatar,name')->find($note['created_by']);
            $note['avatar'] = $user['avatar'];
            $note['created_by_name'] = $user['name'];
            return $note;
        }
        return [];
    }

    /**
     * 工单人员消息处理
     * @param $workOrderId
     * @param $userId
     * @return array|bool|int|string
     * @throws \Exception
     */
    public function workOrderUserRemindAdd($workOrderId, $userId)
    {
        //其他工单人员小红点处理
        //其他工单人员的小红点只会出现在处理按钮中 回复消息的如果是自己 (应当排除创建人和接收人在工单人员里的小红点) 排除自己
        $taskWorkOrderList = model(TaskWorkOrderUserModel::class)->where(["work_order_id" => $workOrderId])->field("id,user_id")->select();
        $taskWorkOrderUserIds = [];
        $taskWorkOrderIds = [];
        $result = [];
        foreach ($taskWorkOrderList as $taskWorkOrderListItem) {
            $taskWorkOrderUserIds[$taskWorkOrderListItem['user_id']] = $taskWorkOrderListItem['user_id'];
            $taskWorkOrderIds[$taskWorkOrderListItem['user_id']] = $taskWorkOrderListItem['id'];
        }

        if (!isset($taskWorkOrderUserIds[$userId])) {
            throw new LogicException('task member user not exist', ErrorCode::TASK_MEMBER_USER_NOT_EXIST);
        }

        //排除当前用户不给自己提醒
        unset($taskWorkOrderIds[$userId]);
        if (!empty($taskWorkOrderIds)) {
            $result = model(TaskWorkOrderUserModel::class)->where(["id" => ["IN", join(",", $taskWorkOrderIds)]])->save(["message_unread" => "yes"]);
        }
        return $result;
    }

    /**
     * 修改工单
     * @param $data
     * @param $userId
     * @return array|bool
     * @throws \Exception
     */
    public function updateTaskWorkOrder($data, $userId)
    {
        // 查询工单数据是否存在
        $taskWorkOrder = model(TaskWorkOrderModel::class)
			->field('id,status')
			->where(['id' => $data['id']])
			->find();
        //判断一下,防止工单不存在,异常出错提示
        if (empty($taskWorkOrder)) {
            throw new LogicException("task work order not found", ErrorCode::TASK_WORK_ORDER_NOT_EXIST);
        }
        // 已处理和已撤销的的工单无需操作
		if(in_array($taskWorkOrder['status'], [TaskWorkOrderModel::STATUS_EXPIRED,TaskWorkOrderModel::STATUS_PROCESSED])){
			return [];
		}

		//结单判断,没有环节确认的全部撤销,有环节未确认的撤销
		$taskWorkOrderProblemStepCategory = model(TaskWorkOrderProblemStepCategoryModel::class)
			->where(['task_work_order_id' => $data['id']])
			->select();
		if (empty($taskWorkOrderProblemStepCategory)) {
            //工单改为结单时操作,不在存在环节确认工单更新为撤销状态
			//增加工单操作流程如果工单没有确认环节,更新工单为已撤销
            if($data['status'] == TaskWorkOrderModel::STATUS_PROCESSED){
                $data['status']  = TaskWorkOrderModel::STATUS_EXPIRED;
            }

		} else {
			// 确认环节数据检查
			foreach ($taskWorkOrderProblemStepCategory as $taskWorkOrderProblemStepCategoryItem) {
				if ($taskWorkOrderProblemStepCategoryItem['is_confirm'] == TaskWorkOrderProblemStepCategoryModel::IS_CONFIRM_DEFAULT) {
					//如果工单存在问题环节未确认,并且是非本环节的 工单状态修改成已撤销
					$data['status'] = TaskWorkOrderModel::STATUS_EXPIRED;
					//更新未确认的工单环节
					$updateData     = [
						'id' => $taskWorkOrderProblemStepCategoryItem['id'],
						'is_confirm' => 'no', // 未确认的工单确认状态
						'plan_end_time' => time(), //批量操作时间记录
						'confirm_person' => $userId //批量操作用户信息记录
					];
					model(TaskWorkOrderProblemStepCategoryModel::class)->modifyItem($updateData);
				}
			}
	}
        //判断工序分类信息是否在存
        if (isset($data['category_id'])) {
            $category = CategoryService::getInstance()->getOne(['id' => $data['category_id']], 'name');
            //填补结单原因
            $data['report_type'] = $category['name'] ?? '';
        }
        // 添加工单备注图片
        if (isset($data['note_media'])) {
            $mediaIds = [];
            $mediaService = MediaService::getInstance();
            // 添加图片
            foreach ($data['note_media'] as $noteMedia) {
                if (isset($noteMedia['id'])) {
                    $mediaIds[] = $noteMedia['id'];
                    continue;
                }
                // 生成图片
                $mediaService->generateMediaData($noteMedia);
                // 添加图片
                $mediaData = $mediaService->addMediaData($noteMedia);
				$mediaIds[] = $mediaData['id'];
            }
            $data['task_work_order_media'] = implode(',', $mediaIds);
        }
        // 处理工单备注 上报描述
		if (isset($data['text'])) {
			$note = model(NoteModel::class)
				->field('id')
				->where([
				'link_id' => $data['id'],
				'module_id' => module_by_code('task_work_order')['id'],
			])->find();

			if (!empty($note)) {
				$noteUpdateData = ['id' => $note['id'], 'text' => $data['text']];
				if (isset($data['task_work_order_media'])) {
					$noteUpdateData['note_media'] = $data['task_work_order_media'];
				}
				// 处理自定义字段
				$noteUpdateData = CommonService::instance('note')->dealUpdateCustomField($noteUpdateData, 'note');
				// 修改备注
				model(NoteModel::class)->modifyItem($noteUpdateData);
			}
			$data['report_content'] = $data['text'];
		}
        // 更新工单信息
		$data['close_at'] = time();
        $updateData = CommonService::instance('task_work_order')->dealUpdateCustomField($data, 'task_work_order');
        return model(TaskWorkOrderModel::class)->modifyItem($updateData);
    }

    /**
     * 解析内部执行人筛选
     * @param $executorFilter
     * @param $insideExecutor
     */
    public function parseInsideExecutorFilter(&$executorFilter, $insideExecutor)
    {
        $userIdList = array_column($insideExecutor, 'user_id');
        if (count($userIdList)) {
            $executorFilter[] = [
                'task.executor' => ['IN', implode(',', $userIdList)],
            ];
        }
    }

    /**
     * 处理反馈工单
     * @param $data
     * @return string
     * @throws Exception
     * @throws Throwable
     */
    public function dealReviewFeedbackTaskWorkOrder($data)
    {
        $taskWorkOrderId = $data['id'];
        $isConfirm = $data['is_confirm'];
        $taskWorkOrder = model(TaskWorkOrderModel::class)->field('id,task_id,review_request_node_id,status')->find($taskWorkOrderId);

        if (empty($taskWorkOrder)) {
            throw new LogicException('task work order not exist', ErrorCode::TASK_WORK_ORDER_NOT_EXIST);

        }

        switch ($taskWorkOrder['status']) {
            case TaskWorkOrderModel::STATUS_PROCESSED:
                throw new LogicException("task work order already processed", ErrorCode::TASK_WORK_ORDER_ALREADY_PROCESSED);
            case TaskWorkOrderModel::STATUS_EXPIRED:
                throw new LogicException("task work order already expired", ErrorCode::TASK_WORK_ORDER_ALREADY_PROCESSED);
        }

        $taskId = $taskWorkOrder['task_id'];
        $reviewRequestNodeId = $taskWorkOrder['review_request_node_id'];

        $reviewRequestNode = model(ReviewRequestNodeModel::class)->find($reviewRequestNodeId);
        if (empty($reviewRequestNode)) {
            throw new LogicException("review_request_node_not_exist", ErrorCode::REVIEW_REQUEST_NODE_NOT_EXIST);
        }

        $reviewRequestService = ReviewRequestService::getInstance();
        $reviewRequestId = $reviewRequestNode['review_request_id'];
        $reviewRequest = model(ReviewRequestModel::class)->find($reviewRequestId);

        $isTaskWorkOrder = model(TaskWorkOrderModel::class)->save(['id' => $taskWorkOrderId, 'status' => 1]);

        //更新成功 则处理状态
        if ($isTaskWorkOrder) {
            if ($isConfirm === "yes") { //为yes直接通过
                $reviewRequestService->refuseReviewFeedback($reviewRequestNode, $reviewRequest, $taskId);
            } else { //如果为no 则为通过修改任务状态为以提交以及版本列表子项状态以提交,修改任务为通过,二次确认为yes
                $reviewRequestService->waitFeedbackDeal($reviewRequestNode);
            }

            // 制片接受或者拒绝，减少未处理数据记录
            Client::send('count_pending', build_queue_data_with_xu([
                'type' => 'review_submit_feedback',
                'mode' => 'sub',
                'data' => ["id" => $taskId]
            ]));
        }

        return $isTaskWorkOrder;
    }

    /**
     * 制作管理
     * @param array $param
     * @param int $currentTenantId
     * @return array
     */
    public function processManage(array $param, int $currentTenantId)
    {
//        $stepCategoryId = $param['filter']['step_category_id'];
//        $module = $this->getModuleByStepCategoryId($stepCategoryId);
//        $userService = new LoginService();
//        $departmentInfo = $userService->getDepartmentInfo();
//        $departmentIdList = array_column($departmentInfo, 'department_id', 'department_id');
//        if (count($departmentIdList)) {
//            return [];
//        }
        if (isset($param['filter']['project_id'])) {
            $param['filter']['task.project_id'] = $param['filter']['project_id'];
        }
        $statusList = array_column(model(StatusModel::class)->field('id,code')->select(), 'id', 'code');
        $filter = $this->parseMultipleEntityTaskFilter($param['filter']);

        $filter['task.step_type'] = 'step';
        $filter["JSON_UNQUOTE(JSON_EXTRACT(entity.json, CONCAT('$.', module.code, '_status')))"] = ['NEQ', $statusList['closed']];
//        $filter['entity.module_id'] = $module['id'];
        // todo 刷好历史department_id后 加上部门id筛选
//        $filter['task.department_id'] = ['IN', array_values($departmentIdList)];
        // 通过筛选条件查询任务id
        $primaryIdList = model(ModuleModel::class)->join('entity on entity.module_id = module.id')
            ->join('task on task.entity_id = entity.id')
            ->join('task_work_order on task_work_order.type = \'task_making\' and task_work_order.task_id = task.id', 'LEFT')
            ->where($filter)->group('task.id')->field('task.id')->page(...$param['page'])->select();
        $taskIdList = array_column($primaryIdList, 'id');
        if (count($taskIdList) === 0) {
            return [];
        }

        $queryFields = [
            'task.id', 'task.name', 'task.task_status', 'task.name', 'task.code', 'task.plan_end_time', 'task.executor', 'task.executor_tenant_id', 'task.tenant_id',
            'entity.id', 'entity.name', 'entity.initial_episode_code', 'entity.showings_number', 'entity.module_id', 'entity.entity_id', 'entity.entity_module_id', 'entity.json'
        ];
        // 查询任务和实体数据
        $data = model(EntityModel::class)->join('task on task.entity_id = entity.id')->where(['task.id' => ['IN', $taskIdList]])->field(build_complex_query_fields($queryFields, '__'))->order('task.plan_end_time ASC')->select();
        $outsideSupplierTenantId = [];
        $executorUserIdList = [];
        $statusIdList = [];
        $parentEntityIdList = [];
        foreach ($data as &$task) {
            $task = separate_complex_query_data($task, '__');
            if ($task['task']['executor'] > 0) {
                $executorUserIdList[$task['task']['executor']] = $task['task']['executor'];
            } else if ($task['task']['executor_tenant_id'] > 0 && $task['task']['executor_tenant_id'] != $currentTenantId) {
                $outsideSupplierTenantId[$task['task']['executor_tenant_id']] = $task['task']['executor_tenant_id'];
            }
            if ($task['task']['task_status'] > 0) {
                $statusIdList[$task['task']['task_status']] = $task['task']['task_status'];
            }
            if ($task['entity']['entity_id'] > 0) {
                $parentEntityIdList[$task['entity']['entity_id']] = $task['entity']['entity_id'];
            }
            if (isset($task['entity']['json'])) {
                $task['entity']['json'] = json_decode($task['entity']['json'], true);
                foreach ($task['entity']['json'] as $jsonField => $jsonValue) {
                    $field = explode('_', $jsonField);
                    if (count($field) > 1) {
                        $jsonField = str_replace_once(array_shift($field) . '_', '', $jsonField);
                    }
                    $task['entity'][$jsonField] = $jsonValue;
                }
                unset($task['entity']['json']);
            }
        }

        // 供应商信息
        $supplierRes = TaskService::getInstance()->queryTaskSupplierInfo($currentTenantId, [], $outsideSupplierTenantId, [], $executorUserIdList);


        $parentEntityList = [];
        // sequence 查询
        unset($parentEntityIdList[0]);
        if (count($parentEntityIdList) > 0) {
            $parentEntityList = model(EntityModel::class)->where(['id' => ['IN', array_keys($parentEntityIdList)]])->field('id,name,code')->select();
            $parentEntityList = array_column($parentEntityList, null, 'id');
        }


        // 查询任务状态
        $statusList = [];
        if (count($statusIdList) > 0) {
            $statusList = model(StatusModel::class)->where(['id' => ['IN', $statusIdList]])->select();
            $statusList = array_column($statusList, null, 'id');
        }
        // 查询版本数据
        $versionModuleId = Module::$moduleDictData['module_index_by_code']['task']['id'];
        $maxVersionList = model(VersionModel::class)->where(['module_id' => $versionModuleId, 'link_id' => ['IN', $taskIdList]])->field('id,number,link_id')->select();
        $maxVersionList = array_column($maxVersionList, null, 'link_id');
        // 查询工单数据
        $workOrderList = model(TaskWorkOrderModel::class)
            ->where(['type' => 'task_making', 'task_id' => ['IN', $taskIdList]])
            ->field('id,task_id,number,status,type')->select();
        $workOrderList = array_column($workOrderList, null, 'task_id');
        // 组装数据
        $dataFormatCallback = function ($item) use (&$maxVersionList, &$workOrderList, &$statusList, &$supplierRes, &$parentEntityList) {
            $item[Module::$moduleDictData['module_index_by_id'][$item['entity']['module_id']]['code'] ?? $item['entity']['module_id']] = &$item['entity'];
            $item['version'] = $maxVersionList[$item['task']['id']] ?? null;
            $item['task_work_order'] = $workOrderList[$item['task']['id']] ?? null;
            $item['task_status'] = $statusList[$item['task']['task_status']] ?? null;
            $item['executor_info'] = null;
            if ($item['task']['executor_tenant_id'] > 0 && $item['task']['executor_tenant_id'] != $item['task']['tenant_id']) {
                $item['executor_info'] = $supplierRes['outside'][$item['task']['executor_tenant_id']] ?? null;
            } elseif ($item['task']['executor'] > 0) {
                $item['executor_info'] = $supplierRes['executor'][$item['task']['executor']] ?? null;
            }
            if ($item['entity']['entity_module_id'] > 0) {
                $item[Module::$moduleDictData['module_index_by_id'][$item['entity']['entity_module_id']]['code'] ?? $item['entity']['entity_module_id']] = $parentEntityList[$item['entity']['entity_id']] ?? null;
            }
            return $item;
        };

        return array_map($dataFormatCallback, $data);
    }

    /**
     * 通过分类id获得模块
     * @param $stepCategoryId
     * @return mixed|null
     */
    public function getModuleByStepCategoryId($stepCategoryId)
    {
        $secondStepCategory = model(StepCategoryModel::class)->find($stepCategoryId);
        if ($secondStepCategory['parent_id'] === 0) {
            return Module::$moduleDictData['module_index_by_id'][$secondStepCategory['entity_id']] ?? null;
        }
        $topStepCategory = model(StepCategoryModel::class)->find($secondStepCategory['parent_id']);
        return Module::$moduleDictData['module_index_by_id'][$topStepCategory['entity_id']] ?? null;

    }

    /**
     * 获取序列映射
     * @param $entityIdList
     * @return array
     */
    public function getEntityListMap($entityIdList)
    {
        $entityList = [];
        $entityIdList = array_filter(array_unique($entityIdList), function ($item) {
            return (int)$item > 0;
        });
        if (!empty($entityIdList)) {
            $entityList = model(EntityModel::class)->where(['id' => ['IN', $entityIdList]])->field('id,name,code')->select();
            $entityList = array_column($entityList, null, 'id');
        }

        return $entityList;
    }

    /**
     * 更新创建者未读
     * @param $taskWorkOrderId
     * @param $isRead
     * @throws \Exception
     */
    public function updateTaskWorkCreatedByUnread($taskWorkOrderId, $isRead)
    {
        $taskWorkOrder = model(TaskWorkOrderModel::class)->field("id,created_by")->find($taskWorkOrderId);

        if (!empty($taskWorkOrder)) {
            $taskWorkOrderUser = model(TaskWorkOrderUserModel::class)->where(['work_order_id' => $taskWorkOrder['id'], "user_id" => $taskWorkOrder["created_by"]])
                ->field("id")->find();

            //更新未读消息
            if (!empty($taskWorkOrderUser)) {
                model(TaskWorkOrderUserModel::class)->save(["id" => $taskWorkOrderUser["id"], "message_unread" => $isRead]);
            }
        }
    }

    /**
     * 清楚掉未读消息
     * @param $data
     * @param $userId
     * @return array|bool|int|string
     * @throws \Exception
     */
    public function clearTaskWorkUnread($data, $userId)
    {
        //清除掉创建人 (其他人员)
        $result = [];

        if ($data['type'] == 'work_order_record') {
            $taskWorkOrder = model(TaskWorkOrderModel::class)->where(['task_id' => $data['id']])->field('id')->select();
            if (!empty($taskWorkOrder)) {
                $taskWorkOrderIds = array_column($taskWorkOrder, 'id');
                $taskWorkOrderUser = model(TaskWorkOrderUserModel::class)->where(['work_order_id' => ["IN", $taskWorkOrderIds], "user_id" => $userId])
                    ->field("id")->select();

                if (!empty($taskWorkOrderUser)) {
                    $taskWorkOrderUserIds = array_column($taskWorkOrderUser, 'id');
                    $result = model(TaskWorkOrderUserModel::class)->where(['id' => ['IN', $taskWorkOrderUserIds]])->save(['message_unread' => 'no']);
                }
            }
        } elseif ($data['type'] == 'deal_work_order') {
            $taskWorkOrder = model(TaskWorkOrderModel::class)->where(['task_id' => $data['id'], 'receiver' => $userId])->field("id")->select();
            if (!empty($taskWorkOrder)) {
                $taskWorkOrderIds = array_column($taskWorkOrder, 'id');
                $taskWorkOrderUser = model(TaskWorkOrderUserModel::class)->where(['work_order_id' => ["IN", $taskWorkOrderIds], "user_id" => $userId])->select();
                if (!empty($taskWorkOrderUser)) {
                    $taskWorkOrderUserIds = array_column($taskWorkOrderUser, 'id');
                    $result = model(TaskWorkOrderUserModel::class)->where(['id' => ['IN', $taskWorkOrderUserIds]])->save(['message_unread' => 'no']);
                }
            }
        }

        return $result;
    }


    /**
     * 获取工单会话
     * @param $param
     * @param $userId
     * @return array|mixed|string
     */
    public function getTaskWorkOrderChat($param, $userId)
    {
        $filter = $param['filter'];
        $page = $param['page'] ?? [1, C('default_page_total')];

        if (!empty($filter['task.project_id'])) {
            $projectList = model(ProjectModel::class)
                ->where(['id' => ['IN', $filter['task.project_id']]])
                ->field('id,belong_project_id')
                ->select();
            $projectIdList = [];
            foreach ($projectList as $project) {
                $projectIdList[$project['id']] = $project['id'];
                $projectIdList[$project['belong_project_id']] = $project['belong_project_id'];
            }
            unset($projectIdList[0]);
            $filter['task.project_id'] = ['IN', array_values($projectIdList)];
        }

        // 如果需要过滤工单状态
        $order = $param['param']['order'] ?? ["task_work_order.im_edited_at desc"];
        $taskWorkOrderIds = model(TaskWorkOrderModel::class)
            ->join('task_work_order_user twou on task_work_order.id =  twou.work_order_id')
            ->join('task on task_work_order.task_id = task.id')
            ->join('entity on task.entity_id = entity.id')
            ->join('project on project.id = entity.project_id')
            ->join('step on step.id = task.step_id')
            ->field($this->workChatListQueryFields)
            ->where($filter)
            ->where(['twou.user_id' => $userId])
            ->where(["task_work_order.chat_global_id !=''"])
            ->order($order)
            ->page($page[0], $page[1])
            ->select();

        if (empty($taskWorkOrderIds)) {
            return [];
        }
        $chatLinkIds = array_column($taskWorkOrderIds, 'id');
        $linkIdFilter = ['-in', $chatLinkIds];

        // 获取工单会话消息
        $requestData = [
            "param" => [
                "filter" => [
                ],
                "chat.link_type" => "task_work_order",
                "chat.link_id" => $linkIdFilter,
                "page" => [$page[0], $page[1]]
            ]
        ];
        $workOrderChatListRequest = teamones_request('teamones-im', 'chat/get_user_chat_list', $requestData);

        if (empty($workOrderChatListRequest['data']['chat_list'])) {
            return [];
        }

        $taskWorkOrderIds = array_column($taskWorkOrderIds, null, 'id');

        // 遍历工单会话,组合工单信息
        foreach ($workOrderChatListRequest['data']['chat_list'] as &$value) {
            $value['work_chat_list'] = $taskWorkOrderIds[$value['link_id']] ?? [];
        }
        return $workOrderChatListRequest['data'];
    }

    /**
     * 获取未读工单会话
     * @param $param
     * @param $userId
     * @return array
     */
    public function getUnreadTaskWorkOrderChat($param, $userId)
    {

        $filter = $param['filter'];
        $page = $param['page'] ?? [1, C('default_page_total')];

        // 获取工单未读会话消息
        $requestData = [
            "param" => [
                "filter" => [
                ],
                "chat.link_type" => "get_work_order_unread_chat",
                "chat.link_id" => [],
                "page" => [$page[0], $page[1]]
            ]
        ];
        $workOrderChatListRequest = teamones_request('teamones-im', 'chat/get_user_chat_list', $requestData);
        if (empty($workOrderChatListRequest['data']['chat_list'])) {
            return [];
        }
        $workOrderChatLinkIds = [];
        foreach ($workOrderChatListRequest['data']['chat_list'] as $value) {
            $workOrderChatLinkIds[] = $value['link_id'];
        }
        if (!empty($filter['task.project_id'])) {
            $projectList = model(ProjectModel::class)
                ->where(['id' => ['IN', $filter['task.project_id']]])
                ->field('id,belong_project_id')
                ->select();
            $projectIdList = [];
            foreach ($projectList as $project) {
                $projectIdList[$project['id']] = $project['id'];
                $projectIdList[$project['belong_project_id']] = $project['belong_project_id'];
            }
            unset($projectIdList[0]);
            $filter['task.project_id'] = ['IN', array_values($projectIdList)];
        }
        $field = 'task_work_order.status,entity.name,entity.initial_episode_code,entity.showings_number,task_work_order.id,';
        $field .= 'task_work_order.chat_global_id,task_work_order.id,task_work_order.number,task_work_order.task_id';
        // 如果需要过滤工单状态
        $order = $param['param']['order'] ?? ["task_work_order.im_edited_at desc"];
        $taskWorkOrderIds = model(TaskWorkOrderModel::class)
            ->join('task_work_order_user twou on task_work_order.id =  twou.work_order_id')
            ->join('task on task_work_order.task_id = task.id')
            ->join('entity on task.entity_id = entity.id')
            ->field($field)
            ->where($filter)
            ->where(['twou.user_id' => $userId])
            ->where(["task_work_order.chat_global_id !=''"])
            ->where(["task_work_order.id" => ['IN', $workOrderChatLinkIds]])
            ->page(0, 500)
            ->order($order)
            ->select();

        $taskWorkOrderIds = array_column($taskWorkOrderIds, null, 'id');
        $returnData = [];
        // 遍历工单会话,组合工单信息
        foreach ($workOrderChatListRequest['data']['chat_list'] as &$value) {
            $value['work_chat_list'] = $taskWorkOrderIds[$value['link_id']] ?? [];
            if (!empty($value['work_chat_list'])) {
                $returnData = array_merge($returnData, $workOrderChatListRequest['data']);
            }
        }
        return $returnData;
    }

    /**
     * 获取工单会话
     * @param $taskWorkOrderId
     * @return array|false|mixed|string|null
     */
    public function findTaskWorkOrderChat($taskWorkOrderId)
    {
        // 查询工单信息
        return model(TaskWorkOrderModel::class)
            ->join('task on task_work_order.task_id = task.id', 'left')
            ->join('entity on task.entity_id = entity.id', 'left')
            ->join('project on project.id = entity.project_id')
            ->join('step on step.id = task.step_id')
            ->field($this->workChatListQueryFields)
            ->where(['task_work_order.id' => $taskWorkOrderId])
            ->find();
    }

    /**
     * 发送任务工单接收人通知
     * @param $taskWorkOrder
     * @return void
     */
    public function notifyTaskWorkOrderReceiver($taskWorkOrder)
    {
        $user = model(UserModel::class)->find($taskWorkOrder['receiver']);
        if (empty($user)) {
            throw new LogicException("task_work_order [{$taskWorkOrder['id']}] receiver not found", ErrorCode::USER_NOT_FOUND);
        }
        $requestData = [
            'phone' => $user['phone'],
            'template' => 'task_work_order_notify_receiver',
            'data' => [
                $taskWorkOrder['name'],
                $taskWorkOrder['number'],
            ]
        ];
        teamones_request('teamones-oauth', 'sms/send', $requestData);
    }

    /**
     * 通知工单用户新增成员 工单需要处理
     * @param int $workOrderId
     * @param array $userIdList
     * @return void
     */
    public function notifyTaskWorkOrderUserAdded(int $workOrderId, array $userIdList)
    {
        $userIdStr = implode(',', $userIdList);
        $phoneList = model(UserModel::class)->where(['id' => ['IN', $userIdStr]])->column("phone");
        if (empty($phoneList)) {
            throw new LogicException("task_work_order [{$workOrderId}] added user {$userIdStr} not found", ErrorCode::USER_NOT_FOUND);
        }
        $taskWorkOrder = model(TaskWorkOrderModel::class)->find($workOrderId);

        $dataList = [];
        foreach ($phoneList as $phone) {
            $dataList[] = [
                'phone' => $phone,
                'template' => 'task_work_order_notify_added_user',
                'data' => [
                    $taskWorkOrder['name'],
                    $taskWorkOrder['number'],
                ]
            ];
        }
        $requestData = [
            'data_list' => $dataList
        ];
        teamones_request('teamones-oauth', 'sms/batch_send', $requestData);
    }

    /**
     * 获取混合状态
     * @param $statusName
     * @return false|string[]
     * @throws \Exception
     */
    public function getOptionsMergeItemStatus($statusName)
    {
        $taskWorkOrderStatusConfig = OptionsService::getInstance()->getOptionsConfigItemData("task_work_order_status_config", $statusName, TaskWorkOrderModel::STATUS_UNTREATED);
        return explode(',', $taskWorkOrderStatusConfig);
    }

    /**
     * 创建工单note
     * @param $data
     * @param $taskData
     * @param $tenantId
     * @param $createTaskWorkOrder
     * @param $reviewRequest
     * @return array
     * @throws Throwable
     */
    public function addTaskWorkOrderNote($data, $taskData, $tenantId, $createTaskWorkOrder, $reviewRequest)
    {
        //关联的内容使用note表 同步Note表数据,note回填审核反馈工单的数据
        if ($data['type'] === "review_feedback" && !empty($reviewRequest)) {
            //更新任务的状态为处理中 以及审核列表子项 为处理中
            $taskService = TaskService::getInstance();
            $taskService->updateTaskDealStatus($taskData['task_id'], 'processing', $reviewRequest);
        }

        $noteData = [
            'type' => 'text',
            'tenant_id' => $tenantId,
            'link_id' => $createTaskWorkOrder['id'],
            'module_id' => Module::$moduleDictData['module_index_by_code']['task_work_order']['id'],
            'text' => $taskData['text'],
        ];

        if (in_array($data['type'], ["task_making"])) {
            $noteData['reason_type'] = $data['reason_type'];
        }

        $createNoteData = [
            'note' => $noteData,
        ];
        if (!empty($data['note_media'])) {
            $createNoteData['note_media'] = $data['note_media'];
        }

        return NoteService::getInstance()->createNote($createNoteData);
    }


    /**
     * 创建工单会话
     * @param $receiverUnionIds
     * @param $taskWorkOrder
     * @param $taskData
     * @return void
     * @throws \Exception
     */
    public function addTaskWorkOrderChat($receiverUnionIds, $taskWorkOrder, $taskData)
    {
        if (empty($receiverUnionIds)) {
            return;
        }

        //工单创建 发送短信通知给接收人
        Hook::listen('task_work_order_created', $taskWorkOrder);

        // 同步IM,创建会话
        $requestData = [
            "data" => [
                "receiver" => $receiverUnionIds,
                "extra_data" => [
                    'link_id' => $taskWorkOrder['id'],
                    'link_type' => 'task_work_order',
                    'from_tenant_id' => $taskWorkOrder['tenant_id'] ?? 0
                ],
                'name' => $taskWorkOrder['number'] . "({$taskData['name']})",
            ]
        ];
        $chatRequest = teamones_request('teamones-im', 'chat/create_chat', $requestData);
        // 工单和会话id绑定
        model(TaskWorkOrderModel::class)->save(['id' => $taskWorkOrder['id'], 'chat_global_id' => $chatRequest['data']['global_id'], 'im_edited_at' => time()]);
    }

    /**
     * 获取默认名称
     * @param $task
     * @return string
     */
    public function getDefaultWorkOrderName($task)
    {
        $entity = model(EntityModel::class)
            ->join('project p on p.id = entity.project_id')
            ->field("entity.initial_episode_code,entity.showings_number,entity.name,p.name as project_name")
            ->where(["entity.id" => $task["entity_id"]])
            ->find();
        if (empty($entity)) {
            throw new LogicException("entity not found", ErrorCode::ENTITY_NOT_FOUND);
        }
        $nameArray = [$entity['project_name'], $entity['initial_episode_code'], $entity['showings_number'], $entity['name'], $task['name']];
        $nameArray = array_filter($nameArray, function ($nameItem) {
            //去除掉空的
            return !empty($nameItem);
        });
        return join("/", $nameArray);
    }

    /**
     * 获取工单下的返修工单
     * @param $param
     * @return array|void[]
     */
    public function getWorkOrderRepairWorkOrder($param)
    {
        $page = $param["page"] ?? [1, C("default_page_total")];
        $filter = $param["filter"] ?? [];
        $order = $param["order"] ?? ["task_repair_order.created desc"];
        $taskWorkOrderList = $this->taskWorkOrderModel
            ->join("repair_task_work_order_relation on repair_task_work_order_relation.task_work_order_id = task_work_order.id")
            ->join("task_repair_order on repair_task_work_order_relation.task_repair_order_id = task_repair_order.id")
            ->where($filter)->page(...$page)->field("task_repair_order.id,task_repair_order.status,task_repair_order.report_type,task_repair_order.repair_reason,task_repair_order.created")->order($order)->select();

        if (empty($taskWorkOrderList)) {
            return [];
        }

        return $taskWorkOrderList;
    }

    /**
     * 获取返修工单受影响的任务
     * @param $param
     * @return array
     */
    public function getRepairOrderAffectedTask($param)
    {
        $page = $param["page"] ?? [1, C("default_page_total")];
        $filter = $param["filter"] ?? [];
        $repairOrderAffectedTaskList = model(RepairOrderAffectedTaskModel::class)->where($filter)->page(...$page)
            ->field("task_repair_order_id,task_id,repair_status")->select();
        if (empty($repairOrderAffectedTaskList)) {
            return [];
        }
        $repairOrderAffectedTaskIds = array_column($repairOrderAffectedTaskList, 'task_id');
        $taskFields = [
            'task.id', 'entity.name', 'entity.initial_episode_code', 'entity.showings_number', 'task.name as task_name',
            "JSON_UNQUOTE(JSON_EXTRACT(entity.json,CONCAT('$.',module.code,'_grade'))) AS grade",
            "JSON_UNQUOTE(JSON_EXTRACT(entity.json,CONCAT('$.',module.code,'_category'))) AS category",
            'task.executor', 'task.plan_end_time', 'task.executor_tenant_id', 'task.tenant_id'
        ];

        $taskList = model(TaskModel::class)
            ->join("entity on task.entity_id = entity.id")
            ->join("module on entity.module_id = module.id")
            ->where(["task.id" => ["IN", $repairOrderAffectedTaskIds]])
            ->field($taskFields)->select();

        $taskMap = [];
        $executor = [];
        foreach ($taskList as $taskItem) {
            $taskMap[$taskItem['id']] = $taskItem;
            if ($taskItem["executor"] > 0 && $taskItem['executor_tenant_id'] == $taskItem['tenant_id']) {
                $executor[$taskItem["executor"]] = $taskItem["executor"];
            }
        }
        $user = [];
        if (!empty($executor)) {
            $executor = array_values($executor);
            $user = model(UserModel::class)->where(["id" => ["IN", $executor]])->field("id,name")->select();
            $user = array_column($user, null, 'id');
        }

        return array_map(function ($repairOrderAffectedTaskItem) use ($taskMap, $user) {
            $repairOrderAffectedTaskItem['task_detail'] = $taskMap[$repairOrderAffectedTaskItem['task_id']];
            $repairOrderAffectedTaskItem['task_detail']['user'] = $user[$repairOrderAffectedTaskItem['task_detail']["executor"]] ?? [];
            return $repairOrderAffectedTaskItem;
        }, $repairOrderAffectedTaskList);
    }

    /**
     * 返修工单任务返修成功消息推送
     * @param $repairTaskWorkOrderAffectedTaskMap
     * @throws \Exception
     */
    public function repairWorkOrderTaskRepairSuccessMessage($repairTaskWorkOrderAffectedTaskMap)
    {
        $repairTaskWorkOrderIds = array_keys($repairTaskWorkOrderAffectedTaskMap);

        //通过返修工单找到发送工单
        $taskWorkOrderList = model(RepairTaskWorkOrderRelationModel::class)
            ->where(["task_repair_order_id" => ["IN", $repairTaskWorkOrderIds]])
            ->field("task_work_order_id,task_repair_order_id")
            ->select();

        if (empty($taskWorkOrderList)) {
            return;
        }

        $taskWorkOrderIds = [];
        $taskWorkOrderAffectedTaskMap = [];
        foreach ($taskWorkOrderList as $taskWorkOrderListItem) {
            $taskWorkOrderIds[$taskWorkOrderListItem["task_work_order_id"]] = $taskWorkOrderListItem["task_work_order_id"];
            if (!isset($taskWorkOrderAffectedTaskMap[$taskWorkOrderListItem["task_work_order_id"]])) {
                $taskWorkOrderAffectedTaskMap[$taskWorkOrderListItem["task_work_order_id"]] = $repairTaskWorkOrderAffectedTaskMap[$taskWorkOrderListItem["task_repair_order_id"]];
            }
        }

        $taskWorkOrderIds = array_values($taskWorkOrderIds);

        //找到未关闭工单
        $untreatedWorkOrderStatus = TaskWorkOrderService::getInstance()->getOptionsMergeItemStatus("untreated");
        $sendRepairWorkOrderList = model(TaskWorkOrderModel::class)->where(["id" => ["IN", $taskWorkOrderIds], "status" => ["IN", $untreatedWorkOrderStatus], 'chat_global_id' => ["NEQ", '']])->select();

        if (empty($sendRepairWorkOrderList)) {
            return;
        }

        //获取任务与实体的拼接名
        $taskIds = array_unique(array_values($repairTaskWorkOrderAffectedTaskMap));
        $taskEntityList = model(EntityModel::class)->join("task on task.entity_id = entity.id")
            ->where(["task.id" => ["IN", $taskIds]])
            ->field("task.id,entity.initial_episode_code,entity.showings_number,entity.name as entity_name,task.name")
            ->select();

        $taskEntityName = [];
        foreach ($taskEntityList as $taskEntityListItem) {
            $nameArray = [$taskEntityListItem['initial_episode_code'], $taskEntityListItem['showings_number'], $taskEntityListItem['entity_name'], $taskEntityListItem['name']];
            $nameArray = array_filter($nameArray, function ($nameItem) {
                //去除掉空的
                return !empty($nameItem);
            });

            $taskEntityName[$taskEntityListItem["id"]] = join("/", $nameArray);
        }

        $taskWorkOrderUserList = model(TaskWorkOrderUserModel::class)
            ->join("user on user.id = task_work_order_user.user_id")
            ->where(["task_work_order_user.work_order_id" => ["IN", $taskWorkOrderIds]])
            ->field("task_work_order_user.work_order_id,user.union_id")->select();
        $taskWorkOrderUserGroup = array_group_by($taskWorkOrderUserList, "work_order_id");

        foreach ($sendRepairWorkOrderList as $taskWorkOrderItem) {
            if (isset($taskWorkOrderUserGroup[$taskWorkOrderItem['id']]) &&
                isset($taskWorkOrderAffectedTaskMap[$taskWorkOrderItem['id']]) &&
                isset($taskEntityName[$taskWorkOrderAffectedTaskMap[$taskWorkOrderItem['id']]])
            ) {
                $imUserIds = array_unique(array_column($taskWorkOrderUserGroup[$taskWorkOrderItem['id']], 'union_id'));
                //找到相关的任务
                $requestData = [
                    "data" => [
                        'receives' => $imUserIds,
                        'content_type' => "task_repair_finish",
                        'global_id' => $taskWorkOrderItem['chat_global_id'],
                        'content_extra_data' => ['work_order_id' => $taskWorkOrderItem['id'], 'repair_task_name' => $taskEntityName[$taskWorkOrderAffectedTaskMap[$taskWorkOrderItem['id']]]],
                    ],
                ];
                teamones_request('teamones-im', 'message/push_work_order_chat_message', $requestData);
            }
        }
    }

    /**
     * 获取实体下的返修工单
     * @param $param
     * @return array|false|mixed|string
     */
    public function getEntityRepairWorkOrder($param)
    {
        $page = $param["page"] ?? [1, C('default_page_total')];
        $taskWorkOrderFields = ["task_repair_order.id", "task.name as step_name", "task.id as task_id", "task_repair_order.report_type", "task_repair_order.repair_reason",
            "task_repair_order.created", "task_repair_order.created_by", "JSON_UNQUOTE(JSON_EXTRACT(task_repair_order.json, '$.task_repair_order_media')) AS task_repair_order_media"];

        $taskWorkOrderList = model(TaskRepairOrderModel::class)
            ->join("task on task_repair_order.repair_task_id = task.id")
            ->where($param["filter"])
            ->page(...$page)
            ->field($taskWorkOrderFields)
            ->select();

        if (empty($taskWorkOrderList)) {
            return [];
        }

        $taskWorkOrderMedias = [];
        $createdBy = [];
        $taskWorkOrderTaskMap = [];
        foreach ($taskWorkOrderList as $index => $taskWorkOrderItem) {
            if (!empty($taskWorkOrderItem["task_repair_order_media"])) {
                $taskWorkOrderMedia = explode(",", $taskWorkOrderItem["task_repair_order_media"]);
                $taskWorkOrderMedias = array_merge($taskWorkOrderMedias, $taskWorkOrderMedia);
                $taskWorkOrderItem["task_repair_order_media"] = $taskWorkOrderMedia;
            }
            $taskWorkOrderList[$index] = $taskWorkOrderItem;
            $createdBy[$taskWorkOrderItem["created_by"]] = $taskWorkOrderItem["created_by"];
            $taskWorkOrderTaskMap[] = ["task_repair_order_id" => $taskWorkOrderItem["id"], "task_id" => $taskWorkOrderItem["task_id"]];
        }

        $repairOrderAffectedTaskNumberMap = [];
        if (!empty($taskWorkOrderTaskMap)) {
            $taskWorkOrderTaskMap["_logic"] = "OR";
            $repairOrderAffectedTaskList = model(RepairOrderAffectedTaskModel::class)
                ->where($taskWorkOrderTaskMap)
                ->field("task_repair_order_id,version_id")
                ->select();

            if (!empty($repairOrderAffectedTaskList)) {
                $versionIds = array_column($repairOrderAffectedTaskList, "version_id");
                $versionIds = array_filter($versionIds, function ($versionId) {
                    return !empty($versionId);
                });

                if (!empty($versionIds)) {
                    $version = model(VersionModel::class)->where(["id" => ["IN", $versionIds]])->field("id,number")->select();
                    $version = array_column($version, null, "id");

                    foreach ($repairOrderAffectedTaskList as $repairOrderAffectedTaskListItem) {
                        if (!empty($version[$repairOrderAffectedTaskListItem["version_id"]])) {
                            $repairOrderAffectedTaskNumberMap[$repairOrderAffectedTaskListItem["task_repair_order_id"]] = $version[$repairOrderAffectedTaskListItem["version_id"]];
                        }
                    }
                }
            }
        }

        $createdBy = array_values($createdBy);
        $userList = model(UserModel::class)->where(["id" => ["IN", $createdBy]])->field("id,name,union_id,avatar")->select();
        $userList = array_column($userList, null, "id");

        //处理图片
        $mediaList = [];
        if (!empty($taskWorkOrderMedias)) {
            $mediaList = model(MediaModel::class)->where([
                'id' => ["IN", $taskWorkOrderMedias]
            ])->field('id,thumb,param')->select();
            $mediaList = array_map(function ($mediaItem) {
                $mediaItem['param'] = json_decode($mediaItem['param'], true);
                return $mediaItem;
            }, $mediaList);

            $mediaList = array_column($mediaList, null, "id");
        }

        foreach ($taskWorkOrderList as $index => $taskWorkOrderItem) {
            $media = [];
            if (!empty($taskWorkOrderItem["task_repair_order_media"])) {
                foreach ($taskWorkOrderItem["task_repair_order_media"] as $taskWorkOrderMediaItem) {
                    if (isset($mediaList[$taskWorkOrderMediaItem])) {
                        $media[] = $mediaList[$taskWorkOrderMediaItem];
                    }
                }
            }
            $taskWorkOrderItem["task_repair_order_media"] = $media;
            if (isset($userList[$taskWorkOrderItem["created_by"]])) {
                $taskWorkOrderItem["user"] = $userList[$taskWorkOrderItem["created_by"]];
            }

            $taskWorkOrderItem["version"] = null;
            if (isset($repairOrderAffectedTaskNumberMap[$taskWorkOrderItem["id"]])) {
                $taskWorkOrderItem["version"] = $repairOrderAffectedTaskNumberMap[$taskWorkOrderItem["id"]];
            }

            $taskWorkOrderList[$index] = $taskWorkOrderItem;
        }

        return $taskWorkOrderList;
    }

    /**
     * 加入工单
     * @param int $taskWorkOrderId
     * @param int $getUserId
     * @return array|bool
     * @throws Exception
     * @throws Throwable
     */
    public function join(int $taskWorkOrderId, int $getUserId)
    {
        $taskWorkOrder = model(TaskWorkOrderModel::class)->find($taskWorkOrderId);
        if (empty($taskWorkOrder)) {
            throw new LogicException('task_work_order not found', ErrorCode::TASK_WORK_ORDER_NOT_EXIST);
        }
        $taskWorkOrderUserFilter = [
            'work_order_id' => $taskWorkOrderId,
            'user_id' => $getUserId,
        ];
        $taskWorkOrderUser = model(TaskWorkOrderUserModel::class)->where($taskWorkOrderUserFilter)->find();
        if (!empty($taskWorkOrderUser)) {
            // 已经在工单里
            throw new LogicException('you are already in this task work order', ErrorCode::ALREADY_IN_TASK_ORDER_ORDER);
        }
        $add = [
            'user_id' => $getUserId,
            'work_order_id' => $taskWorkOrderId,
        ];
        $addedHookData = [
            'add' => [$add],
            'work_order_id' => $taskWorkOrderId,
            'join_type' => 'self',
        ];
        model(TaskWorkOrderUserModel::class)->startTrans();
        try {
            // 添加工单成员
            $res = model(TaskWorkOrderUserModel::class)->addItem($add);

            Hook::listen('task_work_order_user_added', $addedHookData);
            model(TaskWorkOrderUserModel::class)->commit();
        } catch (Throwable $e) {
            model(TaskWorkOrderUserModel::class)->rollback();
            throw $e;
        }
        return $res;
    }

    /**
     * 工单上报类型统计
     * @param $param
     * @param int $userId
     * @param int $tenantId
     * @return array
     */
    public function typeCount($param, int $userId, int $tenantId)
    {
        $filterProcessTime = $param['process_time_filter'] ?? null;
        $filter = $param['filter'] ?? [
            'task_work_order.tenant_id' => $tenantId,
        ];
        if (!empty($filterProcessTime)) {
            $this->parseProcessTimeFilter($filter, $filterProcessTime);
        }
        //按部门查找的条件
        if (!empty($param['work_order_type'])) {
            $this->execModelCategoryFilter($filter, $param['work_order_type'], $param['step_category_code']);
        }
        if (!empty($param['producer_manage_filter'])) {
            ProducerManageService::getInstance()->getSegmentWorkOrderList($filter, $param['producer_manage_filter']);
        }
        // $filter[]['task_work_order.category_id'] = ['GT', 0];
       // $filter['task_work_order.tenant_id'] = $tenantId;
        $filter['task_work_order.type'] = TaskWorkOrderModel::TYPE_TASK_MAKING;
        $closedStatus = StatusService::getInstance()->getTaskDefaultClosedStatus();
        $filter["JSON_UNQUOTE(JSON_EXTRACT(entity.json, CONCAT('$.', module.code, '_status')))"] = ['NEQ', $closedStatus['id']];

        $fields = "task_work_order.category_id,task_work_order.status,count(distinct task_work_order.id) number";
        $group = "task_work_order.category_id,task_work_order.status";
        $list = $this->taskWorkOrderListJoinSelect($param, $filter, $fields, $userId, $tenantId, null, null ,$group);

        $categoryIdList = array_column($list, 'category_id');
        $categoryList = [];
        if (!empty($categoryIdList)) {
            $categoryList = CategoryService::getInstance()->list(['id' => ['IN', $categoryIdList]]);
            $categoryList = array_column($categoryList, null, 'id');
        }

        $taskWorkOrderTypeTop = CategoryService::getInstance()->list(['type' => CategoryModel::TYPE_TASK_WORK_ORDER, 'parent_id' => 0]);
        $taskWorkOrderTypeTopMap = [];

        foreach ($taskWorkOrderTypeTop as $k => &$taskWorkOrderTypeTopItem) {
            $taskWorkOrderTypeTopItem['number'] = 0;
            $taskWorkOrderTypeTopItem['not_processed'] = 0;
            $taskWorkOrderTypeTopItem['children'] = [];
            $taskWorkOrderTypeTopMap[$taskWorkOrderTypeTopItem['id']] = &$taskWorkOrderTypeTop[$k];
        }
        $list = array_group_by($list, 'category_id');

        $res = [
            'total_count' => 0,
        ];
        foreach ($categoryList as $categoryItem) {
            if (!isset($taskWorkOrderTypeTopMap[$categoryItem['parent_id']])) {
                continue;
            }
            $categoryItem['number'] = 0;
            $categoryWorkOrderStatusCountList = $list[$categoryItem['id']] ?? [];
            $notProcessed = 0;
            foreach ($categoryWorkOrderStatusCountList as $categoryWorkOrderStatusCountItem) {
                $categoryItem['number'] += $categoryWorkOrderStatusCountItem['number'];
                if ($categoryWorkOrderStatusCountItem['status'] == TaskWorkOrderModel::STATUS_UNTREATED) {
                    $notProcessed = $categoryWorkOrderStatusCountItem['number'];
                }
            }

            $taskWorkOrderTypeTopMap[$categoryItem['parent_id']]['number'] += $categoryItem['number'];
            $taskWorkOrderTypeTopMap[$categoryItem['parent_id']]['not_processed'] += $notProcessed;
            $taskWorkOrderTypeTopMap[$categoryItem['parent_id']]['children'][] = $categoryItem;
            $res['total_count'] += $categoryItem['number'];
        }
        unset($taskWorkOrderTypeTopItem);
        foreach ($taskWorkOrderTypeTop as $taskWorkOrderTypeTopItem) {
            if ($taskWorkOrderTypeTopItem['not_processed'] > 0) {
                $taskWorkOrderTypeTopItem['number'] = $taskWorkOrderTypeTopItem['not_processed'];
                $res['not_processed'][] = $taskWorkOrderTypeTopItem;
            }
        }
        $res['total'] = $taskWorkOrderTypeTop;
        return $res;
    }


    /**
     * 工作待办-我的工单
     * @param     $param
     * @param int $userid
     * @param int $tenantId
     *
     * @return void|array
     */
    public function getWorkToDoMyTaskWorkOrderList($param , int $userid, int $tenantId)
    {
        // 处理时长
		$filterProcessTime = $param['process_time_filter'] ?? null;
		$filter = $param['filter'] ?? ['task_work_order.tenant_id' => $tenantId];
		$taskStatus = $param['task.status'] ?? null;
		if (!empty($filterProcessTime)) {
			$this->parseProcessTimeFilter($filter, $filterProcessTime);
		}
        //工单的类型
        $filter['task_work_order.type'] = TaskWorkOrderModel::TYPE_TASK_MAKING;
        $filter['task_work_order.tenant_id'] = $tenantId;
		$filter['task_work_order_user.user_id'] = $userid;

        //分页参数
        $page = $param['page'] ?? [1, C("database.database_max_select_rows")];
        //排序条件
        $order = $param['order'] ?? "task_work_order.id DESC";
		// 指定的字段
        $fields = $this->taskWorkOrderFields;

        $statusList = model(StatusModel::class)->field('id,name,code,color,icon')->select();
        $statusModelList = array_column($statusList, 'id', 'code');
        $statusIdList = array_column($statusList, null, 'id');
        $fields = build_complex_query_fields($fields, '__');
        $filter["JSON_UNQUOTE(JSON_EXTRACT(entity.json, CONCAT('$.', module.code, '_status')))"] = ['NEQ', $statusModelList['closed']];
        $filter["JSON_UNQUOTE(JSON_EXTRACT(task.json,'$.task_status'))"] = ["NOT IN", StatusService::getInstance()->byCodeMap(['closed', 'ready_to_publish', 'final'], false, 'id')];
        $group = "task_work_order.id";
        $list = $this->getMyTodoTaskWorkOrderListSelect($param, $filter, $fields,$userid, $tenantId, $page, null , $group);

        if (empty($list)) {
            return [];
        }

        $stepIdList = [];
        $stepCategoryIdList = [];
        $projectIdList = [];
        $userIdList = [];
        $categoryIdList = [];
        $taskWorkOrderIdList = [];
        foreach ($list as $item) {
            if (!empty($item['task__step_id'])) {
                $stepIdList[$item['task__step_id']] = $item['task__step_id'];
            }
            if (!empty($item['task__step_category_id'])) {
                $stepCategoryIdList[$item['task__step_category_id']] = $item['task__step_category_id'];
            }
            if (!empty($item['task_work_order__relate_step_category_id'])) {
                $stepCategoryIdList[$item['task_work_order__relate_step_category_id']] = $item['task_work_order__relate_step_category_id'];
            }
            if (!empty($item['task_work_order__project_id'])) {
                $projectIdList[$item['task_work_order__project_id']] = $item['task_work_order__project_id'];
            }
            if (!empty($item['task_work_order__id'])) {
                $taskWorkOrderIdList[$item['task_work_order__id']] = $item['task_work_order__id'];
            }
            if (!empty($item['task_work_order__created_by'])) {
                $userIdList[$item['task_work_order__created_by']] = $item['task_work_order__created_by'];
            }
            if (!empty($item['task_work_order__receiver'])) {
                $userIdList[$item['task_work_order__receiver']] = $item['task_work_order__receiver'];
            }
            if (!empty($item['task_work_order__category_id'])) {
                $categoryIdList[$item['task_work_order__category_id']] = $item['task_work_order__category_id'];
            }
        }
        $stepMap = [];
        if (!empty($stepIdList)) {
            $stepFields = 'id,name,code';
            $stepMap = model(StepModel::class)
                ->field($stepFields)
                ->where(['id' => ['IN', array_values($stepIdList)]])
                ->select();
            $stepMap = array_column($stepMap, null, 'id');
        }

        $stepCategoryMap = [];
        if (!empty($stepCategoryIdList)) {
            $stepCategoryFields = 'id,name,code';
            $stepCategoryMap = model(StepCategoryModel::class)
                ->field($stepCategoryFields)
                ->where(['id' => ['IN', array_values($stepCategoryIdList)]])
                ->select();
            $stepCategoryMap = array_column($stepCategoryMap, null, 'id');
        }

        $projectMap = [];
        if (!empty($projectIdList)) {
            $projectFields = 'id,name,code,type';
            $projectMap = model(ProjectModel::class)
                ->field($projectFields)
                ->where(['id' => ['IN', array_values($projectIdList)]])
                ->select();
            $projectMap = array_column($projectMap, null, 'id');
        }

        $userMap = [];
        if (!empty($userIdList)) {
            $userFields = 'id,name';
            $userMap = model(UserModel::class)
                ->field($userFields)
                ->where(['id' => ['IN', array_values($userIdList)]])
                ->select();
            $userMap = array_column($userMap, null, 'id');
        }
        $categoryList = [];
        if (!empty($categoryIdList)) {
            $categoryList = CategoryService::getInstance()->getCategoryListWithParent($categoryIdList);
            $categoryList = array_column($categoryList, null, 'id');
        }

        //查询环节原因
        $taskWorkOrderProblemStepCategoryGroup = [];
        $taskWorkOrderRepairTaskMap = [];
        $taskWorkOrderTodoMap = [];
        if (!empty($taskWorkOrderIdList)) {
            $taskWorkOrderProblemStepCategoryList = $this->getProblemStepCategoryInfoList([
                'filter' => [
                    'task_work_order_id' => ["IN", $taskWorkOrderIdList]
                ]
            ], $userid);

            if (!empty($taskWorkOrderProblemStepCategoryList)) {
                $taskWorkOrderProblemStepCategoryGroup = array_group_by($taskWorkOrderProblemStepCategoryList, 'task_work_order_id');
                //留下剩余的工单id查询
                $taskWorkOrderIdList = array_keys($taskWorkOrderProblemStepCategoryGroup);
                $noteList = model(NoteEntityRelationModel::class)
                    ->join('note on note.id = note_entity_relation.note_id')
                    ->where([
                        'note.link_id' => ["IN", $taskWorkOrderIdList],
                        'note.module_id' => module_by_code('task_work_order')['id'],
                        'note_entity_relation.relation_type' => NoteEntityRelationModel::RELATION_TYPE_STEP])
                    ->field("note.link_id,note_entity_relation.task_id")
                    ->select();
                //工单内返修的任务
                $noteTaskIdList = [];
                if (!empty($noteList)) {
                    foreach ($noteList as $noteItem) {
                        $noteTaskIdList[$noteItem['task_id']] = $noteItem['task_id'];
                    }
                    $noteTaskIdList = array_values($noteTaskIdList);
                }

                if (!empty($noteTaskIdList)) {
                    $noteTaskFilter = [
                        ['id' => ["IN", $noteTaskIdList]],
                        [
                            "step_type" => TaskModel::STEP_TYPE_WORK_ORDER_TO_DO,
                            "JSON_UNQUOTE(JSON_EXTRACT(task.json, '$.task_work_order_id'))" => ["IN", $taskWorkOrderIdList]
                        ],
                        "_logic" => "OR"
                    ];
                } else {
                    $noteTaskFilter = [
                        "step_type" => TaskModel::STEP_TYPE_WORK_ORDER_TO_DO,
                        "JSON_UNQUOTE(JSON_EXTRACT(task.json, '$.task_work_order_id'))" => ["IN", $taskWorkOrderIdList]
                    ];
                }

                //查询工单内的待办 以及 工单内返修的任务
                $noteTaskList = model(TaskModel::class)
                    ->where($noteTaskFilter)
                    ->field("id,name,step_type,step_category_id,step_id,plan_end_time,json_unquote(json_extract(task.json,'$.task_status')) as task_status,JSON_UNQUOTE(JSON_EXTRACT(task.json, '$.task_work_order_id')) as task_work_order_id")
                    ->select();

                $repairTaskList = [];
                $todoList = [];
                $stepCategoryIds = [];
                foreach ($noteTaskList as $noteTaskItem) {
                    $noteTaskItem['task_status'] = $statusIdList[$noteTaskItem['task_status']];
                    if ($noteTaskItem["step_type"] == TaskModel::STEP_TYPE_WORK_ORDER_TO_DO) {
                        $todoList[] = $noteTaskItem;
                    } else {
                        $stepCategoryIds[] = $noteTaskItem['step_category_id'];
                        $repairTaskList[$noteTaskItem['id']] = $noteTaskItem;
                    }
                }

                //获取待办的环节
                if (!empty($todoList)) {
                    $taskRelationTag = model(TaskRelationTagModel::class)->where([
                        'task_id' => ["IN", array_column($todoList, "id")],
                        'link_module_code' => "step_category"
                    ])->select();
                    $todoStepCategoryIdMap = array_column($taskRelationTag, 'link_id', 'task_id');
                    $stepCategoryIds = array_unique(array_merge($stepCategoryIds, array_column($taskRelationTag, 'link_id')));
                }

                $stepCategoryList = [];
                if (!empty($stepCategoryIds)) {
                    $stepCategoryList = model(StepCategoryModel::class)->where(['id' => ["IN", $stepCategoryIds]])->select();
                    $stepCategoryList = array_column($stepCategoryList, null, 'id');
                }

                foreach ($todoList as $todoItem) {
                    $todoItem['step_category_id'] = $todoStepCategoryIdMap[$todoItem['id']] ?? 0;
                    $todoItem['step_category_name'] = $stepCategoryList[$todoItem['step_category_id']]['name'] ?? '';
                    $taskWorkOrderTodoMap[$todoItem['task_work_order_id']][] = $todoItem;
                }

                foreach ($noteList as $noteItem) {
                    $repairTaskList[$noteItem['task_id']]['step_category_name'] = $stepCategoryList[$repairTaskList[$noteItem['task_id']]['step_category_id']]['name'] ?? '';
                    $taskWorkOrderRepairTaskMap[$noteItem['link_id']][$noteItem['task_id']] = $repairTaskList[$noteItem['task_id']];
                }
            }
        }
        foreach ($list as &$item) {
            $item = separate_complex_query_data($item, '__');
            $item['project'] = $projectMap[$item['task_work_order']['project_id']] ?? null;
            $item['step'] = $stepMap[$item['task']['step_id']] ?? null;
            $item['step_category'] = $stepCategoryMap[$item['task']['step_category_id']] ?? null;
            $item['relate_step_category'] = $stepCategoryMap[$item['task_work_order']['relate_step_category_id']] ?? null;
            $item['created_by'] = $userMap[$item['task_work_order']['created_by']] ?? null;
            $item['receiver'] = $userMap[$item['task_work_order']['receiver']] ?? null;
            $item['entity'] = array_merge($item['entity'], get_no_prefix_json_fields($item['entity']['json'], module_by_id($item['entity']['module_id'])['code']));
            $item['task_work_order_category'] = $categoryList[$item['task_work_order']['category_id']] ?? null;
            $item['task_work_order_category_parent'] = $item['task_work_order_category']['parent'] ?? null;
            $item['problem_step_category'] = $taskWorkOrderProblemStepCategoryGroup[$item['task_work_order']['id']] ?? [];
            $item['repair_task'] = isset($taskWorkOrderRepairTaskMap[$item['task_work_order']['id']]) ? array_values($taskWorkOrderRepairTaskMap[$item['task_work_order']['id']]) : [];
            $item['todo_task'] = $taskWorkOrderTodoMap[$item['task_work_order']['id']] ?? [];
            unset($item['task_work_order_category']['parent'], $item['entity']['json']);
        }

        return $list;
    }

    /**
     * 我的待办-工单统计
     * @param $param
     * @param int $userId
     * @param int $tenantId
     * @return array
     */
    public function getMyTodoTaskWorkOrderCount($param, int $userId, int $tenantId)
    {
		$filterProcessTime = $param['process_time_filter'] ?? null;
		$filter = $param['filter'] ?? ['task_work_order.tenant_id' => $tenantId];
		$taskStatus = $param['task.status'] ?? null;
		if (!empty($filterProcessTime)) {
			$this->parseProcessTimeFilter($filter, $filterProcessTime);
		}

		$filter['task_work_order.type'] = TaskWorkOrderModel::TYPE_TASK_MAKING;
		$filter['task_work_order.tenant_id'] = $tenantId;
		$filter['task_work_order_user.user_id'] = $userId;

        if (!empty($param['producer_manage_filter'])) {
            ProducerManageService::getInstance()->getSegmentWorkOrderList($filter, $param['producer_manage_filter']);
        }
        $filter['task_work_order.type'] = TaskWorkOrderModel::TYPE_TASK_MAKING;
        $closedStatus = StatusService::getInstance()->getTaskDefaultClosedStatus();
        $filter["JSON_UNQUOTE(JSON_EXTRACT(entity.json, CONCAT('$.', module.code, '_status')))"] = ['NEQ', $closedStatus['id']];
        $filter["JSON_UNQUOTE(JSON_EXTRACT(task.json,'$.task_status'))"] = ["NOT IN", StatusService::getInstance()->byCodeMap(['closed', 'ready_to_publish', 'final'], false, 'id')];

        $fields = "task_work_order.id,task_work_order.category_id,task_work_order.status,count(distinct task_work_order.id) number";
        $group = "task_work_order.id,task_work_order.category_id,task_work_order.status";
        $list = $this->getMyTodoTaskWorkOrderListSelect($param, $filter, $fields, $userId, $tenantId, null, null, $group);

        $categoryIdList = array_column($list, 'category_id');
        $categoryList = [];
        if (!empty($categoryIdList)) {
            $categoryList = CategoryService::getInstance()->list(['id' => ['IN', $categoryIdList]]);
            $categoryList = array_column($categoryList, null, 'id');
        }

        $taskWorkOrderTypeTop = CategoryService::getInstance()->list(['type' => CategoryModel::TYPE_TASK_WORK_ORDER, 'parent_id' => 0]);
        $taskWorkOrderTypeTopMap = [];

        foreach ($taskWorkOrderTypeTop as $k => &$taskWorkOrderTypeTopItem) {
            $taskWorkOrderTypeTopItem['number'] = 0;
            $taskWorkOrderTypeTopItem['not_processed'] = 0;
            $taskWorkOrderTypeTopItem['children'] = [];
            $taskWorkOrderTypeTopMap[$taskWorkOrderTypeTopItem['id']] = &$taskWorkOrderTypeTop[$k];
        }
        $list = array_group_by($list, 'category_id');

        $res = [
            'total_count' => 0,
        ];
		// 处理问题分类
        foreach ($categoryList as $categoryItem) {
            if (!isset($taskWorkOrderTypeTopMap[$categoryItem['parent_id']])) {
                continue;
            }
            $categoryItem['number'] = 0;
            $categoryWorkOrderStatusCountList = $list[$categoryItem['id']] ?? [];
            $notProcessed = 0;
            foreach ($categoryWorkOrderStatusCountList as $categoryWorkOrderStatusCountItem) {
                $categoryItem['number'] += $categoryWorkOrderStatusCountItem['number'];
                if ($categoryWorkOrderStatusCountItem['status'] == TaskWorkOrderModel::STATUS_UNTREATED) {
                    $notProcessed = $categoryWorkOrderStatusCountItem['number'];
                }
            }

            $taskWorkOrderTypeTopMap[$categoryItem['parent_id']]['number'] += $categoryItem['number'];
            $taskWorkOrderTypeTopMap[$categoryItem['parent_id']]['not_processed'] += $notProcessed;
            $taskWorkOrderTypeTopMap[$categoryItem['parent_id']]['children'][] = $categoryItem;
            $res['total_count'] += $categoryItem['number'];
        }
        unset($taskWorkOrderTypeTopItem);
        foreach ($taskWorkOrderTypeTop as $taskWorkOrderTypeTopItem) {
            if ($taskWorkOrderTypeTopItem['not_processed'] > 0) {
                $taskWorkOrderTypeTopItem['number'] = $taskWorkOrderTypeTopItem['not_processed'];
                $res['not_processed'][] = $taskWorkOrderTypeTopItem;
            }
        }

        $res['total'] = $taskWorkOrderTypeTop;

        return $res;
    }

	/**
	 * 工作待办-左侧工单数据统计
	 * @return array
	 */
	public function getTodoTaskStatisticsOnTheLeft($param, int $userId, int $tenantId)
	{
		$filter['task_work_order.tenant_id'] = $tenantId;
		$fields = [
			'DISTINCT task_work_order.id',
		];
		$statusList = model(StatusModel::class)->field('id,name,code,color,icon')->select();
		$statusModelList = array_column($statusList, 'id', 'code');
		$statusIdList = array_column($statusList, null, 'id');
		$filter["JSON_UNQUOTE(JSON_EXTRACT(entity.json, CONCAT('$.', module.code, '_status')))"] = ['NEQ', $statusModelList['closed']];
		$filter["JSON_UNQUOTE(JSON_EXTRACT(task.json,'$.task_status'))"] = ["NOT IN", StatusService::getInstance()->byCodeMap(['closed', 'ready_to_publish', 'final'], false, 'id')];

		return $this->findMyTaskWorkOrderFull($param, $filter, $fields, $userId, $tenantId);
	}
    /**
     * 工单列表查询
     * @param $param
     * @param int $userid
     * @param int $tenantId
     * @return array|mixed|string
     */
    public function list($param, int $userid, int $tenantId)
    {
        $filterProcessTime = $param['process_time_filter'] ?? null;
        $filter = $param['filter'] ?? ['task_work_order.tenant_id' => $tenantId];
        $taskStatus = $param['task.status'] ?? null;
        if (!empty($filterProcessTime)) {
            $this->parseProcessTimeFilter($filter, $filterProcessTime);
        }
        //$filter['task_work_order.tenant_id'] = $tenantId;
        $filter['task_work_order.type'] = TaskWorkOrderModel::TYPE_TASK_MAKING;
        $page = $param['page'] ?? [1, C("database.database_max_select_rows")];
        $order = $param['order'] ?? "task_work_order.id DESC";
		// 指定的字段数据
        $fields = $this->taskWorkOrderFields;

        $statusList = model(StatusModel::class)->field('id,name,code,color,icon')->select();
        $statusModelList = array_column($statusList, 'id', 'code');
        $statusIdList = array_column($statusList, null, 'id');
        $filter["JSON_UNQUOTE(JSON_EXTRACT(entity.json, CONCAT('$.', module.code, '_status')))"] = ['NEQ', $statusModelList['closed']];
        // 任务状态判断
        if(!empty($taskStatus)){
            $filter = [
                "JSON_UNQUOTE(JSON_EXTRACT(task.json,'$.task_status'))" => ["NOT IN", StatusService::getInstance()->byCodeMap(['closed', 'ready_to_publish', 'final'], false, 'id')],
            ];
        }

        $fields = build_complex_query_fields($fields, '__');
        //区分工单是从哪里点击过来的 按部门查找 按环节查 按用户查 区分发出和收到
        if (!empty($param['filter']['task_work_order.type_count'])) {
            if ($param['filter']['task_work_order.type_count'] == 'send_count') {
                $list = $this->getSendTaskWorkOrderList($param, $filter, $fields, $userid, $tenantId, $page, $order);
            }else if($param['filter']['task_work_order.type_count'] == 'receive_count'){
                $list = $this->getReceiveTaskWokOrderList($param, $filter, $fields, $userid, $tenantId, $page, $order);
            }
        } else {
            $list = $this->taskWorkOrderListJoinSelect($param, $filter, $fields, $userid, $tenantId, $page, $order);
        }

        if (empty($list)) {
            return [];
        }

        // 抽取主键
        $stepIdList = [];
        $stepCategoryIdList = [];
        $projectIdList = [];
        $userIdList = [];
        $categoryIdList = [];
        $taskWorkOrderIdList = [];
        foreach ($list as $item) {
            if (!empty($item['task__step_id'])) {
                $stepIdList[$item['task__step_id']] = $item['task__step_id'];
            }
            if (!empty($item['task__step_category_id'])) {
                $stepCategoryIdList[$item['task__step_category_id']] = $item['task__step_category_id'];
            }
            if (!empty($item['task_work_order__relate_step_category_id'])) {
                $stepCategoryIdList[$item['task_work_order__relate_step_category_id']] = $item['task_work_order__relate_step_category_id'];
            }
            if (!empty($item['task_work_order__project_id'])) {
                $projectIdList[$item['task_work_order__project_id']] = $item['task_work_order__project_id'];
            }
            if (!empty($item['task_work_order__id'])) {
                $taskWorkOrderIdList[$item['task_work_order__id']] = $item['task_work_order__id'];
            }
            if (!empty($item['task_work_order__created_by'])) {
                $userIdList[$item['task_work_order__created_by']] = $item['task_work_order__created_by'];
            }
            if (!empty($item['task_work_order__receiver'])) {
                $userIdList[$item['task_work_order__receiver']] = $item['task_work_order__receiver'];
            }
            if (!empty($item['task_work_order__category_id'])) {
                $categoryIdList[$item['task_work_order__category_id']] = $item['task_work_order__category_id'];
            }
        }

        $stepMap = [];
        if (!empty($stepIdList)) {
            $stepFields = 'id,name,code';
            $stepMap = model(StepModel::class)
                ->field($stepFields)
                ->where(['id' => ['IN', array_values($stepIdList)]])
                ->select();
            $stepMap = array_column($stepMap, null, 'id');
        }

        $stepCategoryMap = [];
        if (!empty($stepCategoryIdList)) {
            $stepCategoryFields = 'id,name,code';
            $stepCategoryMap = model(StepCategoryModel::class)
                ->field($stepCategoryFields)
                ->where(['id' => ['IN', array_values($stepCategoryIdList)]])
                ->select();
            $stepCategoryMap = array_column($stepCategoryMap, null, 'id');
        }

        $projectMap = [];
        if (!empty($projectIdList)) {
            $projectFields = 'id,name,code,type';
            $projectMap = model(ProjectModel::class)
                ->field($projectFields)
                ->where(['id' => ['IN', array_values($projectIdList)]])
                ->select();
            $projectMap = array_column($projectMap, null, 'id');
        }

        $userMap = [];
        if (!empty($userIdList)) {
            $userFields = 'id,name';
            $userMap = model(UserModel::class)
                ->field($userFields)
                ->where(['id' => ['IN', array_values($userIdList)]])
                ->select();
            $userMap = array_column($userMap, null, 'id');
        }
        $categoryList = [];
        if (!empty($categoryIdList)) {
            $categoryList = CategoryService::getInstance()->getCategoryListWithParent($categoryIdList);
            $categoryList = array_column($categoryList, null, 'id');
        }

        //查询环节原因
        $taskWorkOrderProblemStepCategoryGroup = [];
        $taskWorkOrderRepairTaskMap = [];
        $taskWorkOrderTodoMap = [];
        if (!empty($taskWorkOrderIdList)) {
            $taskWorkOrderProblemStepCategoryList = $this->getProblemStepCategoryInfoList([
                'filter' => [
                    'task_work_order_id' => ["IN", $taskWorkOrderIdList]
                ]
            ], $userid);

            if (!empty($taskWorkOrderProblemStepCategoryList)) {
                $taskWorkOrderProblemStepCategoryGroup = array_group_by($taskWorkOrderProblemStepCategoryList, 'task_work_order_id');
                //留下剩余的工单id查询
                $taskWorkOrderIdList = array_keys($taskWorkOrderProblemStepCategoryGroup);
                $noteList = model(NoteEntityRelationModel::class)
                    ->join('note on note.id = note_entity_relation.note_id')
                    ->where([
                        'note.link_id' => ["IN", $taskWorkOrderIdList],
                        'note.module_id' => module_by_code('task_work_order')['id'],
                        'note_entity_relation.relation_type' => NoteEntityRelationModel::RELATION_TYPE_STEP])
                    ->field("note.link_id,note_entity_relation.task_id")
                    ->select();
                //工单内返修的任务
                $noteTaskIdList = [];
                if (!empty($noteList)) {
                    foreach ($noteList as $noteItem) {
                        $noteTaskIdList[$noteItem['task_id']] = $noteItem['task_id'];
                    }
                    $noteTaskIdList = array_values($noteTaskIdList);
                }

                if (!empty($noteTaskIdList)) {
                    $noteTaskFilter = [
                        ['id' => ["IN", $noteTaskIdList]],
                        [
                            "step_type" => TaskModel::STEP_TYPE_WORK_ORDER_TO_DO,
                            "JSON_UNQUOTE(JSON_EXTRACT(task.json, '$.task_work_order_id'))" => ["IN", $taskWorkOrderIdList]
                        ],
                        "_logic" => "OR"
                    ];
                } else {
                    $noteTaskFilter = [
                        "step_type" => TaskModel::STEP_TYPE_WORK_ORDER_TO_DO,
                        "JSON_UNQUOTE(JSON_EXTRACT(task.json, '$.task_work_order_id'))" => ["IN", $taskWorkOrderIdList]
                    ];
                }

                //查询工单内的待办 以及 工单内返修的任务
                $noteTaskList = model(TaskModel::class)
                    ->where($noteTaskFilter)
                    ->field("id,name,step_type,step_category_id,step_id,plan_end_time,json_unquote(json_extract(task.json,'$.task_status')) as task_status,JSON_UNQUOTE(JSON_EXTRACT(task.json, '$.task_work_order_id')) as task_work_order_id")
                    ->select();

                $repairTaskList = [];
                $todoList = [];
                $stepCategoryIds = [];
                foreach ($noteTaskList as $noteTaskItem) {
                    $noteTaskItem['task_status'] = $statusIdList[$noteTaskItem['task_status']];
                    if ($noteTaskItem["step_type"] == TaskModel::STEP_TYPE_WORK_ORDER_TO_DO) {
                        $todoList[] = $noteTaskItem;
                    } else {
                        $stepCategoryIds[] = $noteTaskItem['step_category_id'];
                        $repairTaskList[$noteTaskItem['id']] = $noteTaskItem;
                    }
                }

                //获取待办的环节
                if (!empty($todoList)) {
                    $taskRelationTag = model(TaskRelationTagModel::class)->where([
                        'task_id' => ["IN", array_column($todoList, "id")],
                        'link_module_code' => "step_category"
                    ])->select();

                    $todoStepCategoryIdMap = array_column($taskRelationTag, 'link_id', 'task_id');

                    $stepCategoryIds = array_unique(array_merge($stepCategoryIds, array_column($taskRelationTag, 'link_id')));

                }

                $stepCategoryList = [];
                if (!empty($stepCategoryIds)) {
                    $stepCategoryList = model(StepCategoryModel::class)->where(['id' => ["IN", $stepCategoryIds]])->select();
                    $stepCategoryList = array_column($stepCategoryList, null, 'id');
                }

                foreach ($todoList as $todoItem) {
                    $todoItem['step_category_id'] = $todoStepCategoryIdMap[$todoItem['id']] ?? 0;
                    $todoItem['step_category_name'] = $stepCategoryList[$todoItem['step_category_id']]['name'] ?? '';
                    $taskWorkOrderTodoMap[$todoItem['task_work_order_id']][] = $todoItem;
                }

                foreach ($noteList as $noteItem) {
                    $repairTaskList[$noteItem['task_id']]['step_category_name'] = $stepCategoryList[$repairTaskList[$noteItem['task_id']]['step_category_id']]['name'] ?? '';
                    $taskWorkOrderRepairTaskMap[$noteItem['link_id']][$noteItem['task_id']] = $repairTaskList[$noteItem['task_id']];
                }
            }
        }

        foreach ($list as &$item) {
            $item = separate_complex_query_data($item, '__');
            $item['project'] = $projectMap[$item['task_work_order']['project_id']] ?? null;
            $item['step'] = $stepMap[$item['task']['step_id']] ?? null;
            $item['step_category'] = $stepCategoryMap[$item['task']['step_category_id']] ?? null;
            $item['relate_step_category'] = $stepCategoryMap[$item['task_work_order']['relate_step_category_id']] ?? null;
            $item['created_by'] = $userMap[$item['task_work_order']['created_by']] ?? null;
            $item['receiver'] = $userMap[$item['task_work_order']['receiver']] ?? null;
            $item['entity'] = array_merge($item['entity'], get_no_prefix_json_fields($item['entity']['json'], module_by_id($item['entity']['module_id'])['code']));
            $item['task_work_order_category'] = $categoryList[$item['task_work_order']['category_id']] ?? null;
            $item['task_work_order_category_parent'] = $item['task_work_order_category']['parent'] ?? null;
            $item['problem_step_category'] = $taskWorkOrderProblemStepCategoryGroup[$item['task_work_order']['id']] ?? [];
            $item['repair_task'] = isset($taskWorkOrderRepairTaskMap[$item['task_work_order']['id']]) ? array_values($taskWorkOrderRepairTaskMap[$item['task_work_order']['id']]) : [];
            $item['todo_task'] = $taskWorkOrderTodoMap[$item['task_work_order']['id']] ?? [];
            unset($item['task_work_order_category']['parent'], $item['entity']['json']);
        }
        return $list;
    }



    /**
     * 处理工单数据
     * @param  array  $task_work_order
     * @return void
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    private function getProcessTaskWorkOrderData(array $list , int $userid)
    {

        $statusList = model(StatusModel::class)->field('id,name,code,color,icon')->select();
        $statusModelList = array_column($statusList, 'id', 'code');
        $statusIdList = array_column($statusList, null, 'id');

        // 抽取主键
        $stepIdList = [];
        $stepCategoryIdList = [];
        $projectIdList = [];
        $userIdList = [];
        $categoryIdList = [];
        $taskWorkOrderIdList = [];

        foreach ($list as $item) {
            if (!empty($item['task_step_id'])) {
                $stepIdList[$item['task_step_id']] = $item['task_step_id'];
            }
            if (!empty($item['task_step_category_id'])) {
                $stepCategoryIdList[$item['step_category_id']] = $item['step_category_id'];
            }
            if (!empty($item['relate_step_category_id'])) {
                $stepCategoryIdList[$item['relate_step_category_id']] = $item['relate_step_category_id'];
            }
            if (!empty($item['project_id'])) {
                $projectIdList[$item['project_id']] = $item['project_id'];
            }
            if (!empty($item['id'])) {
                $taskWorkOrderIdList[$item['id']] = $item['id'];
            }
            if (!empty($item['created_by'])) {
                $userIdList[$item['created_by']] = $item['created_by'];
            }
            if (!empty($item['receiver'])) {
                $userIdList[$item['receiver']] = $item['receiver'];
            }
            if (!empty($item['category_id'])) {
                $categoryIdList[$item['category_id']] = $item['category_id'];
            }
        }


        $stepMap = [];
        if (!empty($stepIdList)) {
            $stepFields = 'id,name,code';
            $stepMap = model(StepModel::class)
                ->field($stepFields)
                ->where(['id' => ['IN', array_values($stepIdList)]])
                ->select();
            $stepMap = array_column($stepMap, null, 'id');
        }

        $stepCategoryMap = [];
        if (!empty($stepCategoryIdList)) {
            $stepCategoryFields = 'id,name,code';
            $stepCategoryMap = model(StepCategoryModel::class)
                ->field($stepCategoryFields)
                ->where(['id' => ['IN', array_values($stepCategoryIdList)]])
                ->select();
            $stepCategoryMap = array_column($stepCategoryMap, null, 'id');
        }

        $projectMap = [];
        if (!empty($projectIdList)) {
            $projectFields = 'id,name,code,type';
            $projectMap = model(ProjectModel::class)
                ->field($projectFields)
                ->where(['id' => ['IN', array_values($projectIdList)]])
                ->select();
            $projectMap = array_column($projectMap, null, 'id');
        }

        $userMap = [];
        if (!empty($userIdList)) {
            $userFields = 'id,name';
            $userMap = model(UserModel::class)
                ->field($userFields)
                ->where(['id' => ['IN', array_values($userIdList)]])
                ->select();
            $userMap = array_column($userMap, null, 'id');
        }
        $categoryList = [];
        if (!empty($categoryIdList)) {
            $categoryList = CategoryService::getInstance()->getCategoryListWithParent($categoryIdList);
            $categoryList = array_column($categoryList, null, 'id');
        }

        //查询环节原因
        $taskWorkOrderProblemStepCategoryGroup = [];
        $taskWorkOrderRepairTaskMap = [];
        $taskWorkOrderTodoMap = [];
        if (!empty($taskWorkOrderIdList)) {
            $taskWorkOrderProblemStepCategoryList = $this->getProblemStepCategoryInfoList(
                [
                    'filter' => [
                        'task_work_order_id' => ["IN", $taskWorkOrderIdList]
                    ]
                ],
                $userid
            );

            if (!empty($taskWorkOrderProblemStepCategoryList)) {
                $taskWorkOrderProblemStepCategoryGroup = array_group_by($taskWorkOrderProblemStepCategoryList, 'task_work_order_id');
                //留下剩余的工单id查询
                $taskWorkOrderIdList = array_keys($taskWorkOrderProblemStepCategoryGroup);
                $noteList = model(NoteEntityRelationModel::class)
                    ->join('note on note.id = note_entity_relation.note_id')
                    ->where([
                                'note.link_id' => ["IN", $taskWorkOrderIdList],
                                'note.module_id' => module_by_code('task_work_order')['id'],
                                'note_entity_relation.relation_type' => NoteEntityRelationModel::RELATION_TYPE_STEP])
                    ->field("note.link_id,note_entity_relation.task_id")
                    ->select();
                //工单内返修的任务
                $noteTaskIdList = [];
                if (!empty($noteList)) {
                    foreach ($noteList as $noteItem) {
                        $noteTaskIdList[$noteItem['task_id']] = $noteItem['task_id'];
                    }
                    $noteTaskIdList = array_values($noteTaskIdList);
                }

                if (!empty($noteTaskIdList)) {
                    $noteTaskFilter = [
                        ['id' => ["IN", $noteTaskIdList]],
                        [
                            "step_type" => TaskModel::STEP_TYPE_WORK_ORDER_TO_DO,
                            "JSON_UNQUOTE(JSON_EXTRACT(task.json, '$.task_work_order_id'))" => ["IN", $taskWorkOrderIdList]
                        ],
                        "_logic" => "OR"
                    ];
                } else {
                    $noteTaskFilter = [
                        "step_type" => TaskModel::STEP_TYPE_WORK_ORDER_TO_DO,
                        "JSON_UNQUOTE(JSON_EXTRACT(task.json, '$.task_work_order_id'))" => ["IN", $taskWorkOrderIdList]
                    ];
                }

                //查询工单内的待办 以及 工单内返修的任务
                $noteTaskList = model(TaskModel::class)
                    ->where($noteTaskFilter)
                    ->field("id,name,step_type,step_category_id,step_id,plan_end_time,json_unquote(json_extract(task.json,'$.task_status')) as task_status,JSON_UNQUOTE(JSON_EXTRACT(task.json, '$.task_work_order_id')) as task_work_order_id")
                    ->select();

                $repairTaskList = [];
                $todoList = [];
                $stepCategoryIds = [];
                foreach ($noteTaskList as $noteTaskItem) {
                    $noteTaskItem['task_status'] = $statusIdList[$noteTaskItem['task_status']];
                    if ($noteTaskItem["step_type"] == TaskModel::STEP_TYPE_WORK_ORDER_TO_DO) {
                        $todoList[] = $noteTaskItem;
                    } else {
                        $stepCategoryIds[] = $noteTaskItem['step_category_id'];
                        $repairTaskList[$noteTaskItem['id']] = $noteTaskItem;
                    }
                }

                //获取待办的环节
                if ( ! empty($todoList)) {
                    $taskRelationTag = model(TaskRelationTagModel::class)->where(
                        [
                            'task_id'          => ["IN", array_column($todoList, "id")],
                            'link_module_code' => "step_category"
                        ]
                    )->select();

                    $todoStepCategoryIdMap = array_column($taskRelationTag, 'link_id', 'task_id');

                    $stepCategoryIds = array_unique(array_merge($stepCategoryIds, array_column($taskRelationTag, 'link_id')));

                }

                $stepCategoryList = [];
                if (!empty($stepCategoryIds)) {
                    $stepCategoryList = model(StepCategoryModel::class)->where(['id' => ["IN", $stepCategoryIds]])->select();
                    $stepCategoryList = array_column($stepCategoryList, null, 'id');
                }

                foreach ($todoList as $todoItem) {
                    $todoItem['step_category_id'] = $todoStepCategoryIdMap[$todoItem['id']] ?? 0;
                    $todoItem['step_category_name'] = $stepCategoryList[$todoItem['step_category_id']]['name'] ?? '';
                    $taskWorkOrderTodoMap[$todoItem['task_work_order_id']][] = $todoItem;
                }

                foreach ($noteList as $noteItem) {
                    $repairTaskList[$noteItem['task_id']]['step_category_name'] = $stepCategoryList[$repairTaskList[$noteItem['task_id']]['step_category_id']]['name'] ?? '';
                    $taskWorkOrderRepairTaskMap[$noteItem['link_id']][$noteItem['task_id']] = $repairTaskList[$noteItem['task_id']];
                }
            }
        }
        $info = [];
        foreach ($list as $key => $item) {
            $info[$key]['task_work_order']           = $item;
            $info[$key]['project']                   = $projectMap[$item['project_id']] ?? null;
            $info[$key]['step']                      = $stepMap[$item['step_id']] ?? null;
            $info[$key]['step_category']             = $stepCategoryMap[$item['step_category_id']] ?? null;
            $info[$key]['relate_step_category']            = $stepCategoryMap[$item['relate_step_category_id']] ?? null;
            $info[$key]['created_by']                      = $userMap[$item['created_by']] ?? null;
            $info[$key]['receiver']                        = $userMap[$item['receiver']] ?? null;
            $info[$key]['entity']                          = $item['json'];
            $info[$key]['task_work_order_category']        = $categoryList[$item['category_id']] ?? null;
            $info[$key]['task_work_order_category_parent'] = $item['parent'] ?? null;
            $info[$key]['problem_step_category']           = $taskWorkOrderProblemStepCategoryGroup[$item['id']] ?? [];
            $info[$key]['repair_task']                     = isset($taskWorkOrderRepairTaskMap[$item['id']]) ? array_values($taskWorkOrderRepairTaskMap[$item['id']]) : [];
            $info[$key]['todo_task']                       = $taskWorkOrderTodoMap[$item['id']] ?? [];
        }
        unset($list);

        return $info;
    }


    /**
     * 取部门下的用户user_id
     * @param $departmentId
     * @return void
     */
    private function getDepartmenByUserId(int $tenantId ,int $departmentId){
        $result = TenantService::getInstance()->selectDepartmentUser($tenantId,$departmentId);
        $userIds = [];
        foreach ($result as $key => $value){
            $userIds[] = $value['saas_user_id'];
        }
        return $userIds;
    }

    /**
     * 获取指定用户任务task_workd_id 工单id
     * @param $param
     * @return mixed
     */
    private function getByUserIdTaskId($userId)
    {
        $time = ["BETWEEN", $param['created']];
        $map  = [
            'created' => $time,
            'user_id' => $param['user_id']
        ];

        return model(TaskWorkOrderUserModel::class)
            ->where($map)
            ->column('work_order_id');
    }


    /**
     * 处理模型分类筛选条件
     * @param $filter
     * @param $workOrderType
     * @param $stepCategoryCode
     * @return void
     */
    public function execModelCategoryFilter(&$filter, $workOrderType, $stepCategoryCode)
    {
        $modelTag = [];
        // 查询model分类Code
        $stepCategoryIds = [];
        $stepCategoryList = model(StepCategoryModel::class)->where(['code' => ['IN', $stepCategoryCode]])->select();
        if (!empty($stepCategoryCode)) {
            $stepCategoryIds = array_column($stepCategoryList, 'id');
        }
        if (!empty($stepCategoryIds)) {
            // 发出工单
            if ($workOrderType == 'step_category') {
                $filter["task.step_category_id"] = ["IN", $stepCategoryIds];
            }
            // 收到工单
            if ($workOrderType == 'relate_step') {
                $filter["task_work_order.relate_step_category_id"] = ["IN", $stepCategoryIds];
            }
        }
        // 角色模型
        if (in_array('role_model', $stepCategoryCode)) {
            $modelTag = ['角色'];
        }
        // 道具模型
        if (in_array('props_model', $stepCategoryCode)) {
            $modelTag = array_merge($modelTag, ['道具']);
        }
        // 场景模型
        if (in_array('scenes_model', $stepCategoryCode)) {
            $modelTag = array_merge($modelTag, ['场景']);
        }
        if (!empty($modelTag) && in_array('model', $stepCategoryCode)) {
            $filter["JSON_UNQUOTE(JSON_EXTRACT(entity.json, '$.asset_category'))"] = ['IN', $modelTag];
        }
    }

    /**
     * 报表数据
     * @param $param
     * @param $reportType
     * @param $stepCategoryType
     * @param int $getTenantId
     * @return array[]
     */
    public function report($param, $reportType, $stepCategoryType, int $getTenantId)
    {
        $res = [
            'x_name' => [],
            'data' => [],
        ];
        $queryFields = ['count(*) as count', 'task_work_order.report_type',];
        $groupFields = ['task_work_order.report_type'];
        if ($stepCategoryType == 'report_step_category') {
            $stepCategoryField = 'task.step_category_id';
        } else if ($stepCategoryType == 'relate_step_category') {
            $stepCategoryField = 'task_work_order.relate_step_category_id';
        } else {
            throw new LogicException('stepCategoryType data invalid', ErrorCode::DATA_INVALID);
        }
        $queryFields[] = $stepCategoryField . ' AS step_category_id';
        $groupFields[] = $stepCategoryField;
        $filter = $param['filter'] ?? [];
        $filter['task_work_order.tenant_id'] = $getTenantId;
        $filter['task_work_order.type'] = TaskWorkOrderModel::TYPE_TASK_MAKING;
        $filter['task_work_order.report_type'] = ['neq', ''];

        $data = model(TaskWorkOrderModel::class)
            ->join('task on task.id = task_work_order.task_id')
            ->join('entity on entity.id = task.entity_id')
            ->where($filter)
            ->field($queryFields)
            ->group(implode(',', $groupFields))
            ->select();

        if (empty($data)) {
            return $res;
        }
        $stepCategoryIdList = array_column($data, 'step_category_id', 'step_category_id');
        $stepCategoryMap = model(StepCategoryModel::class)
            ->where(['id' => ['IN', $stepCategoryIdList]])
            ->field('id,name')
            ->order('index')
            ->select();
        $stepCategoryMap = array_column($stepCategoryMap, 'name', 'id');

        $dataMap = [];
        foreach ($data as &$item) {
            $item['step_category_name'] = $stepCategoryMap[$item['step_category_id']] ?? '未知';
            $dataMap[sprintf('%s-%s', $item['step_category_name'], $item['report_type'])] = $item['count'];
        }
        // 确定x轴的字段
        if ($reportType == 'task_work_order_report_type') {
            $resX1 = array_unique(array_column($data, 'report_type'));
            $resX2 = array_values($stepCategoryMap);
            $getDataMapValue = function ($x1, $x2) use ($dataMap) {
                return $dataMap[sprintf('%s-%s', $x2, $x1)] ?? 0;
            };
        } elseif ($reportType == 'step_category') {
            $resX1 = array_values($stepCategoryMap);
            $resX2 = array_unique(array_column($data, 'report_type'));
            $getDataMapValue = function ($x1, $x2) use ($dataMap) {
                return $dataMap[sprintf('%s-%s', $x1, $x2)] ?? 0;
            };
        } else {
            throw new LogicException('reportType data invalid', ErrorCode::DATA_INVALID);
        }

        // x轴的列名
        $res['x_name'] = $resX1;
        // 拼接获取数据
        foreach ($resX2 as $resX2Item) {
            $resX2ItemData = [
                'name' => $resX2Item,
                'data' => [],
            ];
            foreach ($resX1 as $xNameItem) {
                $resX2ItemData['data'][] = $getDataMapValue($xNameItem, $resX2Item);
            }
            $res['data'][] = $resX2ItemData;
        }

        return $res;
    }

    /**
     * 解析处理事件筛选条件
     * @param $filter
     * @param $filterProcessTime
     * @return void
     */
    public function parseProcessTimeFilter(&$filter, $filterProcessTime)
    {
        if (count($filterProcessTime) < 2) {
            throw new LogicException('process time filter is invalid', ErrorCode::DATA_INVALID);
        }
        $hours = intval($filterProcessTime[1]);
        if ($filterProcessTime[0] == 'LT') {
            $undoFilter = [
                'LT',
                $hours * 60 * 60
            ];
            $doneFilter = [
                'LT',
                $hours * 60 * 60
            ];
        } else {
            $undoFilter = [
                'GT',
                $hours * 60 * 60
            ];
            $doneFilter = [
                'GT',
                $hours * 60 * 60
            ];
        }

        $filter[] = [
            '_logic' => 'or',
            [
                'task_work_order.status' => ['NEQ', TaskWorkOrderModel::STATUS_PROCESSED],
                time() . ' - task_work_order.created' => $undoFilter,
            ],
            [
                'task_work_order.status' => ['EQ', TaskWorkOrderModel::STATUS_PROCESSED],
                'task_work_order.close_at' => ['GT', 0],
                'task_work_order.close_at - task_work_order.created' => $doneFilter,
            ],
        ];
    }

    /**
     * 复制一个版本，通过任务ID
     * @param int $taskId 任务ID
     * @return array
     * @throws Throwabl
     */
    private function copyVersionByTaskId(int $taskId)
    {
        $versionModel = model(VersionModel::class);
        //复制的字段
        $copyField = 'id,project_id,tenant_id,link_id,module_id,description,json,param';

        $where = [
            'module_id' => module_by_code('task')['id'],
            'link_id' => $taskId,
            'is_publish' => 'yes'
        ];
        $version = $versionModel->field($copyField)->where($where)->order('number DESC')->find();
        if (empty($version)) {
            throw new LogicException('任务没有已发布的版本', ErrorCode::TASK_NOT_FOUND_VERSION);
        }
        //json 转数组
        $version['json'] && $version['json'] = json_decode($version['json'], true);
        $version['param'] && $version['param'] = json_decode($version['param'], true);
        //来源版本ID
        $version['source_version_id'] = $version['id'];
        unset($version['id']);
        //复制操作
        $data = [
            'is_copy' => true,
            'version' => $version,
        ];
        $res = VersionService::getInstance()->create($data);
        return $res;
    }

    /**
     * 上报工单并添加反馈
     * @param     $data
     * @param     $reportType
     * @param int $startRepairTaskId
     * @param int $wantRepairTaskId
     * @param     $workOrderId
     * @param int $userId
     * @param int $unionId
     * @param int $tenantId
     * @return array
     * @throws Throwable
     */
    public function reportAndAddFeedback($data, $reportType, int $startRepairTaskId, int $wantRepairTaskId, $workOrderId, int $userId, int $unionId, int $tenantId)
    {
        $reportCategory = $data['report_category'] ?? "only_report";
        if ($reportType == 'report_and_add_feedback') {
            $workOrderCreateData = [
                'type' => TaskWorkOrderModel::TYPE_TASK_MAKING,
                'receiver' => $data['receiver'] ?? [],
                'task_id' => $startRepairTaskId,
                'text' => $data['note']['text'],
                'reason_type' => $data['note']['reason_type'],
                'task_work_order_cos_media' => $data['note']['note_cos_media'] ?? [],
                'task_work_order_media' => $data['note']['note_media'] ?? [],
                'report_category' => $reportCategory,
                'problem_step_category_ids' => $data['problem_step_category_ids'] ?? [],
                'is_confirm' => $data['is_confirm'] ?? TaskWorkOrderProblemStepCategoryModel::IS_CONFIRM_YES,
                'category_id' => $data['category_id'] ?? 0,
            ];
        }
        if (isset($data['note_relation'])) {
            if ($data['note_relation']['type'] === 'step') {
                $task = model(TaskModel::class)->join('entity on entity.id = task.entity_id')
                    ->where(['task.id' => $data['note_relation']['task_id']])
                    ->field('entity.initial_episode_code,task.step_category_id,task.entity_id,task.project_id')->find();
                $data['note_relation']['step_category_id'] = $task['step_category_id'];
                $data['note_relation']['initial_episode_code'] = $task['initial_episode_code'];
                $data['note_relation']['entity_id'] = $task['entity_id'];
                $data['note_relation']['project_id'] = $task['project_id'];
            }
            $data['note_relation']['relate_module_code'] = $data['note']['module_code'];
            $data['note_relation']['relation_type'] = $data['note_relation']['type'];
        }
        $twm = model(TaskWorkOrderModel::class);
        $res = [];
        $twm->startTrans();
        try {
            if (!empty($workOrderCreateData)) {
                // todo工单 media需要处理
                $res = $workOrderCreate = TaskWorkOrderService::getInstance()->createTaskWorkOrder($workOrderCreateData, $tenantId, $userId, $unionId, false);
                $workOrderId = $workOrderCreate['task_work_order']['id'];
            }
            if (!empty($data['note']['id'])) {
                $res['note'] = ReviewFeedbackService::getInstance()->updateRepairFeedbackNote($data);
                $noteId = $data['note']['id'];
            } else {
                $taskIdList = [$data["start_repair_task_id"], $data["want_repair_task_id"]];
                $taskList = model(TaskModel::class)
                    ->where(["id" => ["IN", $taskIdList]])
                    ->field('step_category_id')
                    ->select();
                $taskStepCategory = array_unique(array_column($taskList, "step_category_id"));
                if (count($taskStepCategory) == 1) {
                    // 组内返修
                    $taskRepairRestricted = ReviewFeedbackService::getInstance()->restrictionAddRepairFeedbackNote([$data["want_repair_task_id"]]);
                    if (!empty($taskRepairRestricted)) {
                        throw new LogicException('task repair stop', ErrorCode::THE_TASK_CANNOT_BE_REPAIRED);
                    }
                }
                $data['note']['link_id'] = $workOrderId;
                $data['note']['demand_type'] = NoteModel::DEMAND_TYPE_REPAIR_FEEDBACK;
                $data['note']['module_id'] = Module::$moduleDictData['module_index_by_code']['task_work_order']['id'];
                $data['note']['demand_status'] = NoteModel::DEMAND_STATUS_PENDING;
                $res['note'] = ReviewFeedbackService::getInstance()->addRepairFeedbackNote($data);
                $noteId = $res['note']['id'];
            }

            if ($reportType == 'report_and_add_feedback') {
                // 发起返修
                TaskRepairOrderService::getInstance()->start([
                    'task_id' => $startRepairTaskId,
                    'type' => 'group_in',
                    'need_repair_task_id' => $wantRepairTaskId,
                    'task_work_order_id' => $workOrderId,
                    'note_id' => $noteId,
                    'send_repair_work_order' => [$workOrderId],
                    'text' => $data['note']['text'],
                ], $userId);
            }

            //仅发布
            if ($reportCategory == 'only_publish') {
                $this->copyVersionByTaskId($startRepairTaskId);
            }

            $twm->commit();
            $noteRelation = model(NoteEntityRelationModel::class)->where(['note_id' => $noteId])->find();
            if (!empty($noteRelation['entity_id'])) {
                $qp = [
                    'task_work_order_id' => $workOrderId,
                    'filter' => [
                        'entity.id' => $noteRelation['entity_id'],
                    ]
                ];
                $res = $this->repairNoteEntityList($qp, [1, 1]);
                if (!empty($res)) {
                    $res[0]['task_work_order_id'] = $workOrderId;
                }
            }
            return $res;
        } catch (Throwable $e) {
            $twm->rollback();
            throw $e;
        }
    }

    /**
     * 工单返修反馈实体列表
     * @param $param
     * @param $page
     * @return array
     */
    public function repairNoteEntityList($param, $page)
    {
        if (isset($param["filter"]['task_member_status_code'])) {
            $statusList = StatusService::getInstance()->getList(['code' => $param["filter"]['task_member_status_code']], 'id');
            $param["filter"]["task.json->>'$.task_status'"] = ['IN', array_column($statusList, 'id')];
            unset($param["filter"]['task_member_status_code']);
        }

        $filter = $param["filter"] ?? [];
        $taskWorkOrderId = $param["task_work_order_id"];
        $order = $param["order"] ?? "note_entity_relation.entity_id,note_entity_relation.step_category_id,note_entity_relation.task_id";

        //以工序来分页
        $noteList = model(NoteEntityRelationModel::class)
            ->join('note on note.id = note_entity_relation.note_id')
            ->join('entity on entity.id = note_entity_relation.entity_id')
            ->join("task on task.id = note_entity_relation.task_id", "LEFT")
            ->where(['note.link_id' => $taskWorkOrderId, 'note.module_id' => module_by_code('task_work_order')['id'],])
            ->where($filter)
            ->field("note_entity_relation.entity_id,note_entity_relation.relation_type,note_entity_relation.step_category_id,note_entity_relation.task_id")
            ->group("note_entity_relation.entity_id,note_entity_relation.relation_type,note_entity_relation.step_category_id,note_entity_relation.task_id")
            ->order($order)
            ->page(...$page)
            ->select();


        if (empty($noteList)) {
            return [];
        }

        $entityIds = [];
        $taskIds = [];
        $stepCategoryIds = [];
        $stepCategoryWhere = [];
        foreach ($noteList as $noteItem) {
            $entityIds[$noteItem['entity_id']] = $noteItem['entity_id'];
            $stepCategoryIds[$noteItem['step_category_id']] = $noteItem['step_category_id'];
            if ($noteItem['relation_type'] === NoteEntityRelationModel::RELATION_TYPE_STEP) {
                $taskIds[] = $noteItem['task_id'];
            } else {
                if (empty($stepCategoryWhere[$noteItem["entity_id"]])) {
                    $stepCategoryWhere[$noteItem["entity_id"]] = [$noteItem['step_category_id']];
                } elseif (!in_array($noteItem['step_category_id'], $stepCategoryWhere[$noteItem["entity_id"]])) {
                    $stepCategoryWhere[$noteItem["entity_id"]][] = $noteItem['step_category_id'];
                }
            }
        }

        $stepCategoryFilterWhere = [];
        if (!empty($stepCategoryWhere)) {
            foreach ($stepCategoryWhere as $stepCategoryWhereIndex => $stepCategoryWhereItem) {
                $stepCategoryFilterWhere[] = [
                    "entity_id" => $stepCategoryWhereIndex,
                    "step_category_id" => ["IN", $stepCategoryWhereItem],
                ];
                $stepCategoryFilterWhere["_logic"] = "OR";
            }

            $stepCategoryFilterWhere = [
                "relation_type" => NoteEntityRelationModel::RELATION_TYPE_STEP_CATEGORY,
                $stepCategoryFilterWhere
            ];
        }


        $taskList = [];
        $taskFilterWhere = [];
        if (!empty($taskIds)) {
            $taskList = model(TaskModel::class)->where(['id' => ["IN", implode(',', $taskIds)]])
                ->field(["task.id as task_id", "task.name as task_name", "task.step_category_id", "task.plan_end_time",
                    "task.executor", "JSON_UNQUOTE(JSON_EXTRACT(task.json,'$.task_status')) AS task_status"])
                ->select();
            $taskList = array_column($taskList, null, 'task_id');

            $statusIds = [];
            $executor = [];
            foreach ($taskList as $taskItem) {
                $statusIds[$taskItem['task_status']] = $taskItem['task_status'];
                if (!empty($taskItem['executor'])) {
                    $executor[$taskItem['executor']] = $taskItem['executor'];
                }
            }
            $statusIds = array_values($statusIds);
            $statusList = model(StatusModel::class)->where(["id" => ["IN", $statusIds]])->field("id,name,code,color")->select();
            $statusMap = array_column($statusList, null, 'id');

            $executorMap = [];
            if (!empty($executor)) {
                $executor = array_values($executor);
                $executorList = model(UserModel::class)->where(["id" => ["IN", $executor]])->field("id,avatar,name")->select();
                $executorMap = array_column($executorList, null, 'id');
            }

            foreach ($taskList as $taskId => $taskItem) {
                $taskItem['status'] = $statusMap[$taskItem['task_status']] ?? null;
                $taskItem['task_member'] = $executorMap[$taskItem['executor']] ?? null;
                $taskList[$taskId] = $taskItem;
            }
            $taskFilterWhere = [
                "relation_type" => NoteEntityRelationModel::RELATION_TYPE_STEP,
                "task_id" => ["IN", $taskIds]
            ];
        }

        $entityList = model(Entitymodel::class)->where(['id' => ["IN", implode(',', $entityIds)]])
            ->field(['id', 'name', 'initial_episode_code', 'showings_number', 'project_id', 'module_id', 'json'])
            ->select();

        $entityListData = [];
        $entityListDataGroupedByModuleList = [];
        foreach ($entityList as $entityItem) {
            $entityListDataGroupedByModuleList[$entityItem['module_id']][] = $entityItem;
        }
        unset($entityList);
        foreach ($entityListDataGroupedByModuleList as $moduleId => $entityListDataGroupedByModuleItem) {
            $moduleCode = module_by_id($moduleId)['code'] ?? '';
            $deignAssetRelationMap = EntityService::getInstance()->getDownstreamEntityIdMap($entityListDataGroupedByModuleItem, $moduleCode);
            foreach ($entityListDataGroupedByModuleItem as $entityItem) {
                $entityItem["category"] = null;
                if (!empty($entityItem["json"])) {
                    $entityJson = json_decode($entityItem["json"], true);
                    unset($entityItem["json"]);
                    $entityItem["category"] = $entityJson[module_by_id($entityItem["module_id"])["code"] . "_category"] ?? null;
                }
                $entityItem['downstream_entity_id'] = $deignAssetRelationMap[$entityItem['id']] ?? 0;
                $entityListData[$entityItem["id"]] = $entityItem;
            }
        }


        $stepCategoryList = model(StepCategoryModel::class)->where(["id" => ["IN", implode(',', $stepCategoryIds)]])->field("id,name")->select();
        $stepCategoryList = array_column($stepCategoryList, null, "id");

        $noteFields = [
            "note_entity_relation.id", "note_entity_relation.note_id", "note.text", "note.module_code", "note.mark_modify", "note.demand_status",
            "note.demand_status as accept_changes", "note.demand_status as repair_progress", "note.json->>'$.note_resolve_time' as note_resolve_time",
            "JSON_UNQUOTE(JSON_EXTRACT(note.json, '$.note_cos_media')) as cos_media",
            "JSON_UNQUOTE(JSON_EXTRACT(note.json, '$.reason_type')) as reason_type",
            "note_entity_relation.task_id", "note_entity_relation.relation_type", "note_entity_relation.entity_id", "note_entity_relation.step_category_id"
        ];


        $noteEntityRelationListWhere = [
            'note.link_id' => $taskWorkOrderId,
            'note.module_id' => module_by_code('task_work_order')['id']
        ];

        if (!empty($taskFilterWhere) && !empty($stepCategoryFilterWhere)) {
            $noteEntityRelationListWhere[] = [$taskFilterWhere, $stepCategoryFilterWhere, "_logic" => "OR"];
        } else {
            if (!empty($taskFilterWhere)) {
                $noteEntityRelationListWhere[] = $taskFilterWhere;
            }

            if (!empty($stepCategoryFilterWhere)) {
                $noteEntityRelationListWhere[] = $stepCategoryFilterWhere;
            }

            $noteEntityRelationListWhere["_logic"] = "AND";
        }

        //查询相关 需求意见

        $noteEntityRelationList = model(NoteEntityRelationModel::class)
            ->join("note on note.id = note_entity_relation.note_id")
            ->where($noteEntityRelationListWhere)
            ->field($noteFields)
            ->select();


        $noteEntityRelationIds = [];
        $cosMedias = [];
        foreach ($noteEntityRelationList as $noteEntityRelationIndex => $noteEntityRelationItem) {
            $noteCosMedia = [];
            if (!empty($noteEntityRelationItem["cos_media"])) {
                $noteCosMedia = explode(",", $noteEntityRelationItem["cos_media"]);
                foreach ($noteCosMedia as $noteCosMediaId) {
                    $cosMedias[] = $noteCosMediaId;
                }
            }
            $noteEntityRelationItem["cos_media"] = $noteCosMedia;
            $noteEntityRelationIds[] = $noteEntityRelationItem["id"];
            $noteEntityRelationList[$noteEntityRelationIndex] = $noteEntityRelationItem;
        }

        //内容,附件
        $cosMediaList = [];
        if (!empty($cosMedias)) {
            $cosMediaList = model(CosMediaModel::class)->where(['id' => ["IN", $cosMedias]])->select();
            $cosMediaList = array_map(function ($cosMediaItem) {
                $cosMediaItem['param'] = json_decode($cosMediaItem['param']);
                return $cosMediaItem;
            }, $cosMediaList);
            $cosMediaList = array_column($cosMediaList, null, 'id');
        }

        //获取受影响的镜头
        $relationNoteEntityRelationList = model(RelationNoteEntityRelationModel::class)
            ->where(["note_entity_relation_id" => ["IN", $noteEntityRelationIds]])
            ->field("id,entity_id,note_entity_relation_id")
            ->select();

        $relationNoteEntityRelationMap = [];
        $totalStoryboardIdList = [];
        foreach ($relationNoteEntityRelationList as $relationNoteEntityRelationItem) {
            $relationNoteEntityRelationMap[$relationNoteEntityRelationItem["note_entity_relation_id"]][$relationNoteEntityRelationItem["entity_id"]] = $relationNoteEntityRelationItem["entity_id"];
            $totalStoryboardIdList[] = $relationNoteEntityRelationItem["entity_id"];
        }
        $storyboardShotIdMap = [];
        if (!empty($totalStoryboardIdList)) {
            $totalStoryboardList = model(EntityModel::class)->where(['id' => ['IN', $totalStoryboardIdList]])->select();
            $storyboardShotIdMap = EntityService::getInstance()->getDownstreamEntityIdMap($totalStoryboardList, 'storyboard');
        }

        $noteEntityRelationMap = [];
        $assetRelationShotList = [];
        foreach ($noteEntityRelationList as $noteEntityRelationItem) {
            $cosMediaTmp = [];

            if ($noteEntityRelationItem["relation_type"] === NoteEntityRelationModel::RELATION_TYPE_STEP_CATEGORY) {
                $noteEntityRelationKey = join("_", [$noteEntityRelationItem["relation_type"], $noteEntityRelationItem["entity_id"], $noteEntityRelationItem["step_category_id"]]);
            } else {
                $noteEntityRelationKey = join("_", [$noteEntityRelationItem["relation_type"], $noteEntityRelationItem["entity_id"], $noteEntityRelationItem["task_id"]]);
            }

            if (!empty($noteEntityRelationItem["cos_media"])) {
                foreach ($noteEntityRelationItem["cos_media"] as $cosMediaId) {
                    if (isset($cosMediaList[$cosMediaId])) {
                        $cosMediaTmp[] = $cosMediaList[$cosMediaId];
                    }
                }
            }

            $noteEntityRelationItem["cos_media"] = $cosMediaTmp;
            // 计算影响镜头个数
            if (isset($relationNoteEntityRelationMap[$noteEntityRelationItem["id"]])) {
                if (!isset($assetRelationShotList[$noteEntityRelationKey])) {
                    $assetRelationShotList[$noteEntityRelationKey] = $relationNoteEntityRelationMap[$noteEntityRelationItem["id"]];
                } else {
                    $assetRelationShotList[$noteEntityRelationKey] = $assetRelationShotList[$noteEntityRelationKey] + $relationNoteEntityRelationMap[$noteEntityRelationItem["id"]];
                }
            }
            $noteEntityRelationItem['note_resolve_time'] = intval($noteEntityRelationItem['note_resolve_time'] ?? 0);
            $noteEntityRelationMap[$noteEntityRelationKey][] = $noteEntityRelationItem;
        }

        foreach ($noteList as &$noteItem) {
            if ($noteItem["relation_type"] === NoteEntityRelationModel::RELATION_TYPE_STEP_CATEGORY) {
                $noteEntityRelationKey = join("_", [$noteItem["relation_type"], $noteItem["entity_id"], $noteItem["step_category_id"]]);
            } else {
                $noteEntityRelationKey = join("_", [$noteItem["relation_type"], $noteItem["entity_id"], $noteItem["task_id"]]);
            }

            $noteItem['key'] = join("_", [$noteItem["relation_type"], $noteItem["entity_id"], $noteItem["step_category_id"], $noteItem["task_id"]]);
            $noteItem = array_merge($noteItem, $entityListData[$noteItem["entity_id"]], $taskList[$noteItem['task_id']] ?? []);
            $noteItem["step_category_name"] = $stepCategoryList[$noteItem["step_category_id"]]["name"];
            $noteItem["affected_shot_count"] = 0;
            $noteItem['affected_shot_list'] = [];
            if (!empty($assetRelationShotList[$noteEntityRelationKey])) {
                foreach ($assetRelationShotList[$noteEntityRelationKey] as $storyboardId) {
                    if (!isset($storyboardShotIdMap[$storyboardId])) {
                        continue;
                    }
                    $noteItem["affected_shot_count"] += 1;
                    $noteItem['affected_shot_list'][] = $storyboardShotIdMap[$storyboardId];
                }
            }
            $noteItem["repair_demand"] = $noteEntityRelationMap[$noteEntityRelationKey] ?? [];
        }

        return $noteList;

    }

    /**
     * 删除工单
     * @param $filter
     * @return array
     * @throws Throwable
     */
    public function delete($filter)
    {
        $taskWorkOrder = model(TaskWorkOrderModel::class)->where($filter)->find();
        if (empty($taskWorkOrder)) {
            throw new LogicException('task_work_order not found', ErrorCode::TASK_WORK_ORDER_NOT_EXIST);
        }

        $chatNotFound = false;
        $chatHasMessage = false;
        if (!empty($taskWorkOrder['chat_global_id'])) {
            try {
                $chatHasMessageRes = teamones_request('teamones-im', 'chat/has_message', ['param' => ['filter' => ['global_id' => $taskWorkOrder['chat_global_id']]]]);
                $chatHasMessage = $chatHasMessageRes['data'];
            } catch (Throwable $e) {
                if ($e->getCode() == -20210145) {
                    $chatNotFound = true;
                } else {
                    throw $e;
                }
            }
        } else {
            $chatNotFound = true;
        }

        $taskWorkOrderTaskList = model(TaskWorkOrderTaskListModel::class)->where(['work_order_id' => $taskWorkOrder['id']])->select();

        $noteList = model(NoteModel::class)->where(['module_id' => module_by_code('task_work_order')['id'], 'link_id' => $taskWorkOrder['id']])->select();

        $latestRelateRepairNote = $this->getLatestRepairNote($taskWorkOrder['id']);
        $res = [];
        $db = model(TaskWorkOrderModel::class);
        $db->startTrans();
        try {
            if (($chatNotFound || !$chatHasMessage) && empty($taskWorkOrderTaskList) && empty($latestRelateRepairNote)) {
                // 直接删除
                $res['task_work_order_delete'] = $db->where(['id' => $taskWorkOrder['id']])->delete();
                // 工单反馈删除
                if (!empty($noteList)) {
                    $res['note_delete'] = model(NoteModel::class)->where(['id' => ['IN', array_column($noteList, 'id')]])->delete();
                }

                if (!$chatNotFound) {
                    $res['chat_disband'] = teamones_request('teamones-im', 'chat/disband_chat', ['param' => [
                        'filter' => [
                            'global_id' => $taskWorkOrder['chat_global_id']
                        ],
                        'skip_admin_check' => 'yes',
                    ]]);
                }
            } else {
                // 修改状态
                $res['task_work_order_update'] = $db->modifyItem(['id' => $taskWorkOrder['id'], 'status' => TaskWorkOrderModel::STATUS_EXPIRED]);
            }
            $db->commit();
            return $res;
        } catch (Throwable $e) {
            $db->rollback();
            throw $e;
        }
    }

    /**
     * 检测创建工单数据
     * @return void
     * @throws \Exception
     */
    public function checkCreateTaskWorkOrderData($data)
    {
        $reviewRequest = [];
        //如果是反馈审核不能为空
        if ($data['type'] === "review_feedback") {
            if (empty($data['version_id'])) {
                throw new LogicException("version id no exits", ErrorCode::DATA_INVALID);
            }
            if (empty($data['review_request_node_id'])) {
                throw new LogicException("review_request_node_id id no exits", ErrorCode::DATA_INVALID);
            }

            $reviewRequestNode = model(ReviewRequestNodeModel::class)->field('id,review_request_id')->find($data['review_request_node_id']);
            if (!empty($reviewRequestNode)) {
                $reviewRequest = model(ReviewRequestModel::class)->find($reviewRequestNode['review_request_id']);
                if ($reviewRequest['is_reviewed'] === 'yes') {
                    throw new LogicException("review request review done", ErrorCode::REVIEW_REQUEST_REVIEW_DONE);
                }
            }
        } elseif ($data['type'] == "task_making") {
            if (empty($data['reason_type'])) {
                throw new LogicException("reason_type no exits", ErrorCode::DATA_INVALID);
            }
        }

        $untreatedWorkOrderStatus = TaskWorkOrderService::getInstance()->getOptionsMergeItemStatus("untreated");
        // 当同类型的工单没处理完不能再次上报
        $taskWorkOrder = model(TaskWorkOrderModel::class)->where(['type' => $data['type'], 'task_id' => $data['task_id']])->field('id,status')
            ->order('id desc')
            ->find();

        if (!empty($taskWorkOrder) && in_array($taskWorkOrder['status'], $untreatedWorkOrderStatus)) {
            throw new LogicException("task work order not finished", ErrorCode::TASK_WORK_ORDER_NOT_FINISHED);
        }

        return $reviewRequest;
    }

    /**
     * 获取问题环节详情列表
     * @param $param
     * @param $userId
     * @return array
     */
    public function getProblemStepCategoryInfoList($param, $userId)
    {
        $filter = $param['filter'] ?? [];
        $taskWorkOrderProblemStepCategoryList = model(TaskWorkOrderProblemStepCategoryModel::class)->where($filter)->select();

        if (empty($taskWorkOrderProblemStepCategoryList)) {
            return [];
        }
        $projectId = $taskWorkOrderProblemStepCategoryList[0]['project_id'];

        //判定当前用户是否能处理
        $stepCategoryIds = array_column($taskWorkOrderProblemStepCategoryList, 'step_category_id');
        $stepCategoryList = model(StepCategoryModel::class)->where(["id" => ["IN", $stepCategoryIds]])->field("id,name")->select();
        $stepCategoryMap = array_column($stepCategoryList, null, 'id');
        $problemStepCategoryOptions = model(ProjectStepCategoryConfirmConfigModel::class)->where([
            'project_id' => $projectId,
            'step_category_id' => ["IN", $stepCategoryIds],
            'type' => ProjectStepCategoryConfirmConfigModel::TYPE_TASK_WORK_ORDER,
            'confirm_user_id' => $userId
        ])->select();

        $handlerStepCategory = array_column($problemStepCategoryOptions, 'step_category_id', 'step_category_id');
        return array_map(function ($taskWorkOrderProblemStepCategoryItem) use ($handlerStepCategory, $stepCategoryMap) {
            //是否审核过了
            //是否能审核
            $taskWorkOrderProblemStepCategoryItem['is_can_confirm'] = isset($handlerStepCategory[$taskWorkOrderProblemStepCategoryItem['step_category_id']]);
            $taskWorkOrderProblemStepCategoryItem['step_category'] = $stepCategoryMap[$taskWorkOrderProblemStepCategoryItem['step_category_id']];
            return $taskWorkOrderProblemStepCategoryItem;
        }, $taskWorkOrderProblemStepCategoryList);
    }

    /**
     * 获取未知环节人员
     * @param $projectId
     * @return array|false|mixed|string
     */
    public function getUnknownProblemStepCategoryMember($projectId)
    {
        //如果为空,拉入所有QA
        $projectId = is_array($projectId) ? ["IN", $projectId] : $projectId;

        $qualityAssuranceList = model(ProjectMemberModel::class)->where([
            "project_id" => $projectId,
            "type" => ProjectMemberModel::MANAGE_TYPE,
            "role_code" => TaskService::QA_CODE
        ])->field("project_id,user_id")->select();
        if (empty($qualityAssuranceList)) {
            return [];
        }


        if (is_array($projectId)) {
            $userList = model(UserModel::class)->where(['id' => ["IN", array_column($qualityAssuranceList, 'user_id')]])->field("id,union_id")->select();
            $userList = array_column($userList, 'union_id', 'id');
            $qualityAssuranceGroup = [];
            foreach ($qualityAssuranceList as $qualityAssuranceItem) {
                $qualityAssuranceGroup[$qualityAssuranceItem['project_id']][] = $userList[$qualityAssuranceItem['user_id']];
            }
            return $qualityAssuranceGroup;
        } else {
            return model(UserModel::class)->where(['id' => ["IN", array_column($qualityAssuranceList, 'user_id')]])->column("union_id");
        }
    }



	/**
	 * 全量查找我的工单数据
	 * @param $param
	 * @param $filter
	 * @param $fields
	 * @param $userid
	 * @param $tenantId
	 * @param $page
	 * @param $order
	 * @param $group
	 *
	 * @return array|false|mixed|string
	 */
	public function findMyTaskWorkOrderFull($param, $filter,$fields, $userid, $tenantId)
	{
		// 只找和我相关的工单
		$filter['task_work_order_user.user_id'] = $userid;
		$filter['task_work_order.status'] = ['in',TaskWorkOrderModel::STATUS_NOT_CLOSED_GROUP];
		$taskWorkOrderQuery = model(TaskWorkOrderModel::class);
		$taskWorkOrderQuery = $taskWorkOrderQuery->join('task_work_order_user on task_work_order_user.work_order_id = task_work_order.id');
		$taskWorkOrderQuery = $taskWorkOrderQuery
			->join('task on task.id = task_work_order.task_id')
			->join('entity on entity.id = task.entity_id')
			->join('module on entity.module_id = module.id');
		$taskWorkOrderQuery = $taskWorkOrderQuery->where($filter)->field($fields);
		$taskWorkOrderList =  $taskWorkOrderQuery->count();
		return  ['order_nums' => $taskWorkOrderList];
	}

	/**
	 * @param $param
	 * @param $filter
	 * @param $fields
	 * @param $userid
	 * @param $tenantId
	 * @param $page
	 * @param $order
	 * @param $group
	 *
	 * @return mixed
	 */
	public function getMyTodoTaskWorkOrderListSelect($param, $filter,$fields, $userid, $tenantId, $page, $order , $group = null)
	{
		$param["is_my_received"] = $param["is_my_received"] ?? "no";
		$param["exist_in"] = $param["exist_in"] ?? "no";
		$param["wait_handle_filter"] = $param['wait_handle_filter'] ?? 'no';

		if ($param['exist_in'] === 'yes') {
			$filter['task_work_order_user.user_id'] = $userid;
		}
		$filter['task_work_order.status'] = ['in',TaskWorkOrderModel::STATUS_NOT_CLOSED_GROUP];

		// 是否有部门筛选 , 截至时间 , 未完成
		if ($param['wait_handle_filter'] == 'yes') {
			$statusNotClosedGroup = TaskWorkOrderModel::STATUS_NOT_CLOSED_GROUP;
			$filter['task_work_order.status'] = $filter['task_work_order.status'] ?? ['IN', $statusNotClosedGroup];
		}
        //关联双方的project_id 和belong_project_id
        if (!empty($filter['task_work_order.project_id'])) {
            $project_ids = $this->getProjectByBelongProjectId($filter['task_work_order.project_id'], $tenantId);
            $filter['task_work_order.project_id'] = [
                'IN',
                array_merge(
                    $project_ids,
                    array_map('intval', $filter['task_work_order.project_id'])
                )
            ];
        }
		//按环节查找的
		if(!empty($param['filter']['task_work_order.step_category_id'])){
			$filter['task_work_order.step_category_id'] = ['IN',explode(',', $param['filter']['task_work_order.step_category_id'][1])];
		}
		// 指定task_work_order
		if(!empty($param['task_work_order_id'])){
			$filter['task_work_order.id'] = ['IN', $param['task_work_order_id']];
		}

		//部门查询
		if (!empty($param['department_id'])) {
			$departmentUserList = TenantService::getInstance()->selectDepartmentUser($tenantId, ["param" => [
				"filter" => [
					"department_id" => $param['department_id'],
				]
			]])['rows'] ?? [];
			$userIds = [];
			foreach ($departmentUserList as $userListItem) {
				$userIds[$userListItem['saas_user_id']] = $userListItem['saas_user_id'];
			}

			if (!empty($userIds)) {
				$filter['task_work_order_user.user_id'] = ["IN", $userIds];
			}
		}

		//按用户查找的
		if (!empty($param['user_id'])) {
			$filter['task_work_order_user.user_id'] = ["IN", explode(',', $param['user_id'])];
		}

		$taskWorkOrderQuery = model(TaskWorkOrderModel::class);
		$isExistTable = [
			"task_work_order_user." => false,
			"task_work_order_problem_step_category." => false
		];
		//判定是否需要连接哪些表
		$this->checkExistTable($filter, $isExistTable);
		$isAllExist = false;
		if ($isExistTable["task_work_order_user."]) {
			$taskWorkOrderQuery = $taskWorkOrderQuery->join('task_work_order_user on task_work_order_user.work_order_id = task_work_order.id');
			$isAllExist = true;
		}

		if ($isExistTable["task_work_order_problem_step_category."]) {
			//发出工单状态判断按环节查找条件 发出的工单
			$twopscSql = "task_work_order_problem_step_category on task_work_order_problem_step_category.task_work_order_id = task_work_order.id";
			if(!empty($filter['task_work_order_problem_step_category.is_confirm'])){
				$is_confrim = $filter['task_work_order_problem_step_category.is_confirm'];
				$parts = explode(",", $is_confrim[1]);
				$quotedParts = array_map(function ($part) {
					return '"' . $part . '"';
				}, $parts);
				$outputString = implode(",", $quotedParts);
				// setp_category_id
				$stepSql = "task_work_order_problem_step_category on task_work_order_problem_step_category.task_work_order_id = task_work_order.id and task_work_order_problem_step_category.id in (select max(id) from task_work_order_problem_step_category as tt where tt.task_work_order_id = task_work_order.id and tt.is_confirm IN ($outputString) group by id)";

				if (!empty($filter['task_work_order.step_category_id']) || !empty($filter['task_work_order_problem_step_category.step_category_id'])) {
					$taskWorkOrderQuery = $taskWorkOrderQuery->join($stepSql);
				}else{
					$taskWorkOrderQuery = $taskWorkOrderQuery->join($twopscSql);
				}
			}else{
				$taskWorkOrderQuery = $taskWorkOrderQuery->join($twopscSql);
			}
			$isAllExist = true;
		}

		//固定连接的表
		$taskWorkOrderQuery = $taskWorkOrderQuery
			->join('task on task.id = task_work_order.task_id')
			->join('entity on entity.id = task.entity_id')
			->join('module on entity.module_id = module.id');

		//是否有todo 环节id筛选
		if (!empty($param['todo_step_category_id'])) {
			$taskWorkOrderQuery  = $taskWorkOrderQuery->join("task_relation_tag r_step_category on r_step_category.link_module_code in ('step_category', 'show_step_category') and r_step_category.task_id = task.id");
			$filter['r_step_category.link_id'] = ['IN', $param['todo_step_category_id']];
		}

		$taskWorkOrderQuery = $taskWorkOrderQuery->where($filter)->field($fields);

		//是否分页
		if (isset($page)) {
			$taskWorkOrderQuery = $taskWorkOrderQuery->page($page[0], $page[1]);
		}

		// 是否需要分组. 如果存在工单用户查询 ,并且 exist_in 为 no
		if (!isset($group)) {
			if ($isAllExist && $param['exist_in'] === 'no') {
				$taskWorkOrderQuery = $taskWorkOrderQuery->group("task_work_order.id");
			}
		} else {
			$taskWorkOrderQuery = $taskWorkOrderQuery->group($group);
		}
		//是否排序
		if (isset($order)) {
			$taskWorkOrderQuery = $taskWorkOrderQuery->order($order);
		}
		$data =  $taskWorkOrderQuery->select();
		return $data;
	}


	/**
     * 工单列表联合查询
     * @param $param
     * @param $filter
     * @param $fields
     * @param $userid
     * @param $tenantId
     * @param $page
     * @param null $group
     * @param null $order
     * @return array|false|mixed|string
     */
    public function taskWorkOrderListJoinSelect($param, $filter, $fields, $userid, $tenantId, $page = null, $order = null, $group = null)
    {
        $param["is_my_received"] = $param["is_my_received"] ?? "no";
        $param["exist_in"] = $param["exist_in"] ?? "no";
        $param["wait_handle_filter"] = $param['wait_handle_filter'] ?? 'no';

        if ($param['exist_in'] === 'yes') {
            $filter['task_work_order_user.user_id'] = $userid;
        }

        // 是否有部门筛选 , 截至时间 , 未完成
        if ($param['wait_handle_filter'] == 'yes') {
            $statusNotClosedGroup = TaskWorkOrderModel::STATUS_NOT_CLOSED_GROUP;
            $filter['task_work_order.status'] = $filter['task_work_order.status'] ?? ['IN', $statusNotClosedGroup];
        }

        //关联双方的project_id 和belong_project_id
        if(!empty($filter['task_work_order.project_id'])){
            $project_ids = $this->getProjectByBelongProjectId($filter['task_work_order.project_id'], $tenantId);
            array_push($project_ids, intval($filter['task_work_order.project_id']) );
            $filter['task_work_order.project_id'] = ['IN', $project_ids];
        }
        //按环节查找的
        if(!empty($param['filter']['task_work_order.step_category_id'])){
            $filter['task_work_order.step_category_id'] = ['IN',explode(',', $param['filter']['task_work_order.step_category_id'][1])];
        }
		// 指定task_work_order
		if(!empty($param['task_work_order_id'])){
			$filter['task_work_order.id'] = ['IN', $param['task_work_order_id']];
		}

        //部门查询
        if (!empty($param['department_id'])) {
            $departmentUserList = TenantService::getInstance()->selectDepartmentUser($tenantId, ["param" => [
                "filter" => [
                    "department_id" => $param['department_id'],
                ]
            ]])['rows'] ?? [];
            $userIds = [];
            foreach ($departmentUserList as $userListItem) {
                $userIds[$userListItem['saas_user_id']] = $userListItem['saas_user_id'];
            }

            if (!empty($userIds)) {
                $filter['task_work_order_user.user_id'] = ["IN", $userIds];
            }
        }

        //按用户查找的
        if (!empty($param['user_id'])) {
            $filter['task_work_order_user.user_id'] = ["IN", explode(',', $param['user_id'])];
        }

        $taskWorkOrderQuery = model(TaskWorkOrderModel::class);
        $isExistTable = [
            "task_work_order_user." => false,
            "task_work_order_problem_step_category." => false
        ];
        //判定是否需要连接哪些表
        $this->checkExistTable($filter, $isExistTable);
        $isAllExist = false;
        if ($isExistTable["task_work_order_user."]) {
            $taskWorkOrderQuery = $taskWorkOrderQuery->join('task_work_order_user on task_work_order_user.work_order_id = task_work_order.id');
            $isAllExist = true;
        }

        if ($isExistTable["task_work_order_problem_step_category."]) {
            //发出工单状态判断按环节查找条件 发出的工单
            $twopscSql = "task_work_order_problem_step_category on task_work_order_problem_step_category.task_work_order_id = task_work_order.id";
            if(!empty($filter['task_work_order_problem_step_category.is_confirm'])){
                $is_confrim = $filter['task_work_order_problem_step_category.is_confirm'];
                $parts = explode(",", $is_confrim[1]);
                $quotedParts = array_map(function ($part) {
                    return '"' . $part . '"';
                }, $parts);
                $outputString = implode(",", $quotedParts);
                // setp_category_id
                $stepSql = "task_work_order_problem_step_category on task_work_order_problem_step_category.task_work_order_id = task_work_order.id and task_work_order_problem_step_category.id in (select max(id) from task_work_order_problem_step_category as tt where tt.task_work_order_id = task_work_order.id and tt.is_confirm IN ($outputString) group by id)";

                if (!empty($filter['task_work_order.step_category_id']) || !empty($filter['task_work_order_problem_step_category.step_category_id'])) {
                    $taskWorkOrderQuery = $taskWorkOrderQuery->join($stepSql);
                }else{
                    $taskWorkOrderQuery = $taskWorkOrderQuery->join($twopscSql);
                }
            }else{
                $taskWorkOrderQuery = $taskWorkOrderQuery->join($twopscSql);
            }
            $isAllExist = true;
        }

        //固定连接的表
        $taskWorkOrderQuery = $taskWorkOrderQuery
            ->join('task on task.id = task_work_order.task_id')
            ->join('entity on entity.id = task.entity_id')
            ->join('module on entity.module_id = module.id');

        //是否有todo 环节id筛选
        if (!empty($param['todo_step_category_id'])) {
            $taskWorkOrderQuery  = $taskWorkOrderQuery->join("task_relation_tag r_step_category on r_step_category.link_module_code in ('step_category', 'show_step_category') and r_step_category.task_id = task.id");
            $filter['r_step_category.link_id'] = ['IN', $param['todo_step_category_id']];
        }

        $taskWorkOrderQuery = $taskWorkOrderQuery->where($filter)->field($fields);

        //是否分页
        if (isset($page)) {
            $taskWorkOrderQuery = $taskWorkOrderQuery->page($page[0], $page[1]);
        }

        // 是否需要分组. 如果存在工单用户查询 ,并且 exist_in 为 no
        if (!isset($group)) {
            if ($isAllExist && $param['exist_in'] === 'no') {
                $taskWorkOrderQuery = $taskWorkOrderQuery->group("task_work_order.id");
            }
        } else {
            $taskWorkOrderQuery = $taskWorkOrderQuery->group($group);
        }
        //是否排序
        if (isset($order)) {
            $taskWorkOrderQuery = $taskWorkOrderQuery->order($order);
        }
        $data =  $taskWorkOrderQuery->select();
        return $data;
    }

    /**
     * 根据传入的参数不同查询不同状态的工单
     * @param $param
     * @param $filter
     * @param $fields
     * @param $userid
     * @param $tenantId
     * @param $page
     * @param $order
     * @param $group
     * @return array|false|mixed|object[]|string|\think\Collection|\think\Model[]|\think\model\RelationModel[]
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getSendTaskWorkOrderList($param, $filter, $fields, $userid, $tenantId, $page = null, $order = null, $group = null)
    {
        //关联双方的project_id 和belong_project_id
        if(!empty($filter['task_work_order.project_id'])){
            $project_ids = $this->getProjectByBelongProjectId($filter['task_work_order.project_id'], $tenantId);
            array_push($project_ids, intval($filter['task_work_order.project_id']) );
            $filter['task_work_order.project_id'] = ['IN', $project_ids];
        }
        //部门查询
        if (!empty($param['department_id'])) {
            $departmentUserList = TenantService::getInstance()->selectDepartmentUser($tenantId, ["param" => [
                "filter" => [
                    "department_id" => $param['department_id'],
                ]
            ]])['rows'] ?? [];
            $userIds = [];
            foreach ($departmentUserList as $userListItem) {
                $userIds[$userListItem['saas_user_id']] = $userListItem['saas_user_id'];
            }

            if (!empty($userIds)) {
                $filter['task_work_order_user.user_id'] = ["IN", $userIds];
            }
        }

        //按用户
        if(!empty($param['user_id'])){
            $filter['task_work_order_user.user_id'] = $userid;
        }

        //按环节进行查找
        if(!empty($param['filter']['task_work_order.step_category_id'])){
            $filter['task_work_order.step_category_id'] = ['IN',explode(',', $param['filter']['task_work_order.step_category_id'][1])];
        }


        $taskWorkOrderQuery = model(TaskWorkOrderModel::class);
        $isExistTable = [
            "task_work_order_user." => false,
            "task_work_order_problem_step_category." => false
        ];
        //判定是否需要连接哪些表
        $this->checkExistTable($filter, $isExistTable);
        $isAllExist = false;
        if ($isExistTable["task_work_order_user."]) {
            $taskWorkOrderQuery = $taskWorkOrderQuery->join('task_work_order_user on task_work_order_user.work_order_id = task_work_order.id');
            $isAllExist = true;
        }

        if ($isExistTable["task_work_order_problem_step_category."]) {
            $taskWorkOrderQuery = $taskWorkOrderQuery->join('task_work_order_problem_step_category on task_work_order_problem_step_category.task_work_order_id = task_work_order.id');
            $isAllExist = true;
        }

        //固定连接的表
        $taskWorkOrderQuery = $taskWorkOrderQuery
            ->join('task on task.id = task_work_order.task_id')
            ->join('entity on entity.id = task.entity_id')
            ->join('module on entity.module_id = module.id');

        //是否有todo 环节id筛选
        if (!empty($param['todo_step_category_id'])) {
            $taskWorkOrderQuery  = $taskWorkOrderQuery->join("task_relation_tag r_step_category on r_step_category.link_module_code in ('step_category', 'show_step_category') and r_step_category.task_id = task.id");
            $filter['r_step_category.link_id'] = ['IN', $param['todo_step_category_id']];
        }

        $taskWorkOrderQuery = $taskWorkOrderQuery->where($filter)->field($fields);

        //是否分页
        if (isset($page)) {
            $taskWorkOrderQuery = $taskWorkOrderQuery->page($page[0], $page[1]);
        }

        // 是否需要分组. 如果存在工单用户查询 ,并且 exist_in 为 no
        if (!isset($group)) {
            if ($isAllExist && $param['exist_in'] === 'no') {
                $taskWorkOrderQuery = $taskWorkOrderQuery->group("task_work_order.id");
            }
        } else {
            $taskWorkOrderQuery = $taskWorkOrderQuery->group($group);
        }

        //是否排序
        if (isset($order)) {
            $taskWorkOrderQuery = $taskWorkOrderQuery->order($order);
        }

        $data =  $taskWorkOrderQuery->select();
        return $data;
    }

    /**
     * 根据不同的参数查询不同状态下收到的工单
     * @param $param
     * @param $filter
     * @param $fields
     * @param $userid
     * @param $tenantId
     * @param $page
     * @param $order
     * @param $group
     * @return array|false|mixed|object[]|string|\think\Collection|\think\Model[]|\think\model\RelationModel[]
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getReceiveTaskWokOrderList($param, $filter, $fields, $userid, $tenantId, $page = null, $order = null, $group = null)
    {
        if(!empty($filter['task_work_order.project_id'])){
            $project_ids = $this->getProjectByBelongProjectId($filter['task_work_order.project_id'], $tenantId);
            array_push($project_ids, intval($filter['task_work_order.project_id']) );
            $filter['task_work_order.project_id'] = ['IN', $project_ids];
        }
        //获取当前用户user_id 关联的工单相关数据

        //部门查询
        if (!empty($param['department_id'])) {
            $departmentUserList = TenantService::getInstance()->selectDepartmentUser($tenantId, ["param" => [
                "filter" => [
                    "department_id" => $param['department_id'],
                ]
            ]])['rows'] ?? [];
            $userIds = [];
            foreach ($departmentUserList as $userListItem) {
                $userIds[$userListItem['saas_user_id']] = $userListItem['saas_user_id'];
            }

            if (!empty($userIds)) {
                $filter['task_work_order_user.user_id'] = ["IN", $userIds];
            }else{
                $filter['task_work_order_user.user_id'] = $userid;
            }
        }
        //按用户
        if(!empty($param['user_id'])){
            $filter['task_work_order_user.user_id'] = $userid;
        }
        //按环节进行查找
        if(!empty($param['filter']['task_work_order.step_category_id'])){
            $filter['task_work_order.step_category_id'] = ['IN',explode(',', $param['filter']['task_work_order.step_category_id'][1])];
        }
        $taskWorkOrderQuery = model(TaskWorkOrderModel::class);
        $isExistTable = [
            "task_work_order_user." => false,
            "task_work_order_problem_step_category." => false
        ];
        //判定是否需要连接哪些表
        $this->checkExistTable($filter, $isExistTable);
        $isAllExist = false;
        if ($isExistTable["task_work_order_user."]) {
            $taskWorkOrderQuery = $taskWorkOrderQuery->join('task_work_order_user on task_work_order_user.work_order_id = task_work_order.id');
            $isAllExist = true;
        }
        if ($isExistTable["task_work_order_problem_step_category."]) {
            $taskWorkOrderQuery = $taskWorkOrderQuery->join('task_work_order_problem_step_category on task_work_order_problem_step_category.task_work_order_id = task_work_order.id');
            $isAllExist = true;
        }

        //固定连接的表 收到的工单全部计算出来
        $taskWorkOrderQuery = $taskWorkOrderQuery
            ->join('task on task.id = task_work_order.task_id')
            ->join('entity on entity.id = task.entity_id')
            ->join('module on entity.module_id = module.id');

        $taskWorkOrderQuery = $taskWorkOrderQuery->where($filter)->field($fields);
        //是否分页
        if (isset($page)) {
            $taskWorkOrderQuery = $taskWorkOrderQuery->page($page[0], $page[1]);
        }
        // 是否需要分组. 如果存在工单用户查询 ,并且 exist_in 为 no
        if (!isset($group)) {
            if ($isAllExist && $param['exist_in'] === 'no') {
                $taskWorkOrderQuery = $taskWorkOrderQuery->group("task_work_order.id");
            }
        } else {
            $taskWorkOrderQuery = $taskWorkOrderQuery->group($group);
        }
        //是否排序
        if (isset($order)) {
            $taskWorkOrderQuery = $taskWorkOrderQuery->order($order);
        }
        $data =  $taskWorkOrderQuery->select();
        return $data;
    }

    /**
     * 关联双方的project_id
     * @param $projectId
     * @return array|false|mixed|string
     */
    public function getProjectByBelongProjectId($projectId , $tenantId)
    {
        // 根据项目id 判断是否关联 belogn_project_id 判断用户是否是甲方 todo ...
        $project = model(ProjectModel::class)
            ->field(['id'])
            ->where(["belong_project_id" => ['IN',$projectId]])
            ->where(["JSON_UNQUOTE(JSON_EXTRACT(json,'$.project_status'))" => ['IN', [1, 3, 4, 7]]])
            ->select();

        return array_unique(array_column($project, 'id'));
    }


    /**
     * 检测是否存在工单用户筛选
     * @param $filter
     * @param $isExistTable
     * @return void
     */
    public function checkExistTable($filter, &$isExistTable)
    {
        foreach ($filter as $key => $value) {
            foreach ($isExistTable as $isExistTableKey => $isExistTableItem) {
                if (empty($isExistTableItem) && strpos($key, $isExistTableKey) !== false) {
                    $isExistTable[$isExistTableKey] = true;
                } elseif (is_array($value)) {
                    $this->checkExistTable($value, $isExistTable);
                }
            }
        }
    }

    /**
     * 获取工单默认配置人员
     * @param $problemStepCategoryIds
     * @param $projectId
     * @return array
     */
    public function getTaskWorkOrderDefaultOptionMember($problemStepCategoryIds, $projectId)
    {
        $defaultMemberUnionIds = [];
        $stepCategoryIds = [];
        if (!empty($problemStepCategoryIds)) {
            $projectProblemStepCategoryOptionsFilter = [
                'project_id' => $projectId,
                'step_category_id' => ["IN", $problemStepCategoryIds],
                'type' => ProjectStepCategoryConfirmConfigModel::TYPE_TASK_WORK_ORDER
            ];
            $projectProblemStepCategoryOptions = ProjectStepCategoryConfirmConfigService::getInstance()
                ->selectUnionIdProjectStepCategoryOptions($projectProblemStepCategoryOptionsFilter);

            //问题确认人
            $defaultMemberUnionIds = array_column($projectProblemStepCategoryOptions, 'confirm_union_id');
            $stepCategoryIds = array_column($projectProblemStepCategoryOptions, 'step_category_id');
        }

        //未知环节,拉入所有QA //只要存在一个环节没有配置,就需要将qa拉入
        if (empty($problemStepCategoryIds) || !empty(array_diff($problemStepCategoryIds, $stepCategoryIds))) {
            $qaMember = $this->getUnknownProblemStepCategoryMember($projectId);
            $defaultMemberUnionIds = array_merge($defaultMemberUnionIds, $qaMember);
        }

        return array_unique($defaultMemberUnionIds);
    }

    /**
     * 是否存在工单默认配置人员
     * @param $problemStepCategoryIds
     * @param $projectId
     * @return bool
     */
    public function isExistTaskWorkOrderDefaultOptionMember($problemStepCategoryIds, $projectId)
    {
        $member = $this->getTaskWorkOrderDefaultOptionMember($problemStepCategoryIds, $projectId);
        return !empty($member);
    }
}
